© Instil Software 2020
TypeScript vs KotlinJS
should you make the
switch?
@BoyleEamonn
Eamonn Boyle
eamonn.boyle@gearset.com
eamonn
garth
@GarthGilmour
Garth Gilmour
garth.gilmour@instil.co
– TS brings types and compilation to JS
– Improves upon the existing strengths of JS
– Makes us more productive and happy
– Leverages existing JS frameworks
– Interop with JS is a design goal
we love typescript
it solves real problems for us
– Kotlin improves upon Java in many ways
– Adds null safety, DSLs, coroutines etc...
– Makes us more productive and happy
– Leverages existing JVM frameworks
– But interop with Java is a design goal
we love kotlin
it solves real problems for us
JVM
Java
Bytecode
Kotlin
(JVM)
Kotlin
(JS)
Browser
JavaScript
Interpreter
Kotlin
(Native)
Machine Code
& Runtime
OS
Kotlin
(Android)
ART
Dalvik
Bytecode
experiment: is kotlinjs worth it?
– We are not using KotlinJS in production
– The code written has been for labs, workshops and talks
– Built several apps both TypeScript and KotlinJS
– Go beyond “hello world”
– Incorporate common JS libraries
– Compare the experience
– Tooling
– Language features
– Community
what problem does it solve?
creating a
kotlinjs react project
– Template project from IntelliJ
– Grade project using Kotlin DSL
– Easily integrate NPM packages
creating new project
the wizard
multiplatform libraries
COMMON
KOTLIN
KOTLIN ANDROID
KOTLIN JS
KOTLIN NATIVE
KOTLIN JVM
NATIVE
ARTEFACT
JS BUNDLE
JAR
standard library documentation
excellent compatibility docs
configuring the kotlin gradle dsl
plugins{
kotlin("js")version"1.6.21"
kotlin("plugin.serialization")version"1.6.21"
}
group="org.example"
version="1.0-SNAPSHOT"
valktorVersion="2.0.2"
repositories{ mavenCentral()}
dependencies{ ...}
configuring the kotlin gradle dsl
kotlin{
js(LEGACY){
binaries.executable()
browser{
commonWebpackConfig{
cssSupport.enabled=true
}
}
}
}
There is a new IR compiler
tasks in the kotlin gradle dsl
add multiplatform and kotlinjs packages
kotlinjs, multiplatform and npm
dependencies {
implementation("org.jetbrains.kotlin-wrappers:kotlin-react:17.0.2-pre.290-kotlin-1.6.10")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:17.0.2-pre.290-kotlin-1.6.10")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-router-dom:6.3.0-pre.340-compat")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-css:17.0.2-pre.290-kotlin-1.6.10")
implementation(npm("bootstrap", "4.6.0"))
implementation(npm("jquery", "1.9.1- 3"))
implementation(npm("popper.js", "^1.16.1"))
}
what’s the code like
standard main function
funmain() {
valcontainer= document.createElement("div")
document.body!!.appendChild(container)
valapp=App.create()
render(app,container)
}
what’s the code like
easy access to browser apis
funmain() {
valcontainer= document.createElement("div")
document.body!!.appendChild(container)
valapp=App.create()
render(app,container)
}
what’s the code like
easy access to react library
valApp=FC<Props>("Application"){
BrowserRouter{
div{
p{ Link{ to="/hello”+"SimpleComponent”}}
}
div{
Routes{
Route{
// …
}
}
}
}
community
Round
1
its popularity continues to grow
rising star on language rankings
…
18 Kotlin
…
https://redmonk.com/sogrady/2021/03/01
/language-rankings-1-21/
The RedMonk
Programming Language
Rankings: January 2021
its popularity continues to grow
rising star on language rankings
https://insights.stackoverflow.com/survey/2020
Stack Overflow Developer
Survey 2020
Most Used Language
13th Kotlin
1st JavaScript
8th TypeScript
its popularity continues to grow
loved by its users
https://insights.stackoverflow.com/survey/2020
Stack Overflow Developer
Survey 2020
Most Loved Language
2nd TypeScript
4th Kotlin
10th JavaScript
1st Rust
TS is the largest alternative to JS
https://2021.stateofjs.com/en-US/
– TypeScript is more popular than KotlinJS
– As a superset of JS, reusing knowledge and assets is easier
– And the transition for JS developers to TS is easier
– TypeScript is well established in the JavaScript world
– Many libraries include TypeScript definitions
– DefinitelyTyped contains many more
community, maturity and support
typescript > kotlin
interop with javascript
Round
2
– Only a few first class wrappers provided
– It is easy to add NPM packages yourself
– But how easy is it to consume that code in Kotlin?
importing npm js packages
gradle dsl
dependencies {
. . .
implementation(npm("react-three-fiber", "4.2.20"))
implementation(npm("react-use-gesture", "7.0.15"))
implementation(npm("three", "0.119.1"))
}
really easy
external declarations
@file:JsModule("react-three-fiber")
@file:JsNonModule
...
external val Canvas: RClass<RProps>
external fun extend(objects: Any)
external fun useFrame(callback: (dynamic, Double) -> Unit)
external fun useThree(): dynamic
external interface PointerEvent {
val uv: Vector2
}
Specify the NPM package
Define any items you
wish to use
– Converts TypeScript d.ts files to Kotlin external declarations
– Still experimental
– At time of writing, on hold until IR compiler stabilises
dukat
automatic generation
https://kotlinlang.org/docs/js-external-declarations-with-dukat.html
– Command line tool
– Installable in isolation via npm
– Simply point to a .d.ts file and it will do the rest
dukat
usage
$ dukat index.d.ts index.module_my-library.kt
$ npm install dukat
dukat
export function getString(): string;
export function setString(input: string): void;
external fun getString(): String
external fun setString(input: String)
– Integrated into Gradle
– Generates definitions for configured packages
dukat
usage
Dukat tasks
-----------
generateExternals
generateExternalsIntegrated
dukat
export interface BasicInterface {
readonly field1: number;
method1(): boolean;
}
export function buildInterface(): BasicInterface;
export type ReadOnlyBasicInterface = Readonly<BasicInterface>;
external interface BasicInterface {
var field1: Number
fun method1(): Boolean
}
external fun buildInterface(): BasicInterface
typealias ReadOnlyBasicInterface = Readonly<BasicInterface>
– It’s a good help but has issues
– Limited by differences in the languages
– Not a seamless workflow
– This situation may improve as the tool and Kotlin evolves
not a silver bullet
square peg and a round hole
– KotlinJS supports a dynamic type
– You can use it in place of any type
– Assign it a value of any type
– Access and use members with any name
– Basically switches off type checking
– This can be used to quickly patch over APIs
dynamic
get out of jail type
external fun useFrame(callback: (dynamic, Double) -> Unit)
– Object literals are common in JavaScript
– KotlinJS has a helper function to create objects
– This is strongly typed (inferred) but requires fields to be var
jso
object literals in kotlinjs
Block(jso {
position = brick.location.toVector3()
color = brick.color
})
– We can embed JavaScript directly with the js function
– The code can even use Kotlin variables
– Must be a compile time constant
– Cannot be a runtime evaluated expression
js
embedding javascript
private fun getToken(): String? {
val tokenKey = TokenKey
return js("""
localStorage.getItem(tokenKey)
""")
}
– As a superset, TypeScript has to win this one
– The type system is geared to support JavaScript
– Lots of libraries already provide TypeScript definition files
– However, writing external declaration in KotlinJS is easy
– Dukat exists but has fundamental limitations
– You may have to write custom translation code on top
interop with javascript
typescript > kotlinjs
jsx vs dsl
Round
3
JSX
IN
TYPESCRIPT
JSX embeds markup
inside JS / TS code
export const TaskItem: FC<Props> = (props) =>
<tr key={props.taskIndex}>
<td>{props.task.text}</td>
<td>
<span onClick={props.onToggle}>
{pickIcon(props.task.done)}
</span>
</td>
</tr>
val TaskItem= functionalComponent<TaskItemProps>("TaskItem"){ props ->
tr{
td { +props.task.text }
td {
span {
+pickIcon(props.task.done)
}
attrs {
onClickFunction= { props.onToggle() }
}
}
}
}
fun RBuilder.TaskItem(task: Task) = child(TaskItem) {
attrs {
this.task = task
}
}
REACT
DSL
IN
KOTLIN
In Kotlin a DSL
provides equivalent
functionality
kotlin DSL’s are very cool
a major advantage
val TaskItem= functionalComponent<TaskItemProps>("TaskItem"){ props ->
tr{
td { +props.task.text }
td {
span {
+pickIcon(props.task.done)
}
attrs {
onClickFunction= { props.onToggle() }
}
}
}
}
fun RBuilder.TaskItem(task: Task) = child(TaskItem) {
attrs {
this.task = task
}
}
REACT
DSL
IN
KOTLIN
JSX is clearly a lot
simpler / shorter
Then they rewrote it
(without telling anyone)
val TaskItem=FC<TaskItemProps>("TaskItem"){props->
tr{
td{ +props.task.text}
td{
onClick={ props.onToggle()}
span{
+pickIcon(props.task.done)
}
}
}
}
REACT
DSL
IN
KOTLIN
val TaskItem=FC<TaskItemProps>("TaskItem"){props->
tr{
td{ +props.task.text}
td{
onClick={ props.onToggle()}
span{
+pickIcon(props.task.done)
}
}
}
}
REACT
DSL
IN
KOTLIN
Builder functions
not required
Many attributes
are cleaner
attrs section
is gone
The typing is ... imperfect
interface InputHTMLAttributes<T> extends HTMLAttributes<T> {
max?: number | string;
min?: number | string;
value?: string | ReadonlyArray<string> | number;
...
}
Type union
type PropsWithChildren<P> = P & { children?: ReactNode };
Type intersection
// Type exports erased!
external fun interfaceUnionInput(input: First)
external fun interfaceUnionInput(input: Second)
external fun interfaceUnionOutput(): dynamic /* First | Second */
export type InterfaceUnion = First | Second;
export function interfaceUnionInput(input: InterfaceUnion): void;
export function interfaceUnionOutput(): InterfaceUnion;
Kotlin supports
proper overloads
Not supported on
the return type
external fun interfaceIntersectionInput(input: First /* First & Second */)
external fun interfaceIntersectionOutput(): First /* First & Second */
export type InterfaceIntersection = First & Second;
export function interfaceIntersectionInput(input: InterfaceIntersection): void;
export function interfaceIntersectionOutput(): InterfaceIntersection;
Intersection
dropped
mapped and conditional types
even more power in typescript
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type PromiseType<T extends Promise<any>> =
T extends Promise<infer U> ? U : never;
Type conditional
The languages are simply not
fully compatible
manual workarounds
useEffect
function useEffect(
effect: EffectCallback,
deps?: DependencyList
): void;
type EffectCallback = () => (void | Destructor);
type Destructor = () => void;
useEffect
union return workaround
fun useEffect(
dependencies: RDependenciesList? = null,
effect: () -> Unit
) {
// ...
}
fun useEffectWithCleanup(
dependencies: RDependenciesList? = null,
effect: () -> Rcleanup
) {
// ...
}
useEffect
or other patterns
useEffect { }
useEffect(dep1, dep2) { }
useEffectOnce { }
useEffectOnce {
cleanup {
// Clean up logic goes here
}
}
– Kotlin’s DSL support is a powerful general purpose tool
– But JSX is a single purpose solution that suits React better
– TypeScript’s advanced type system is very powerful
– Union, intersection and mapped types bring sanity to JS
– Kotlin types (unsurprisingly) sit awkwardly on top of JS
jsx vs dsl
typescript > kotlin
async await vs coroutines
Round
4
asynchronous programming
– Async await is a good async solution in JS & TS
– Engineered so it interops with Promises
– Succinct
promises and async/await
async function loadMap(url: string): Promise<void> {
const response = await fetch(url);
const map = await response.text();
// ...
}
coroutines
– Kotlin’s more general coroutines are better
– Works with other patterns than simply async
– In KotlinJS, it works easily with Promises
kotlin > typescript
suspend fun loadMap(url: String) {
val response = window.fetch(url).await()
val map = response.text().await()
// ...
}
coroutines
– Coroutines are more general and powerful
– They can be used with other patterns too
– With suspend functions we don’t need to “await”
kotlin > typescript
suspend fun loadMap(url: String) {
val map = client.get<String>(url)
// ...
}
Ktor Client
coroutines
– Coroutines can be applied to other patterns too
kotlin > typescript
fun infinite() = sequence {
var count = 0
while (true) {
yield(count++)
}
}
elegant syntax
Round
5
– Kotlin doesn’t have the ternary, but has more
– when for basic pattern matching
– if and when are expressions
– Unit instead of void
– Expression bodied functions
– This creates more symmetry in code
expressions
kotlin > typescript
typescript
chained ternaries
const App: FC = () => {
// ...
return (
<div>
// ...
{gameState === GameState.Start ? <StartScreen/> :
gameState === GameState.Playing ? <PlayingGame/> :
gameState === GameState.Dead ? <DeathScreen/> :
gameState === GameState.Win ? <WinScreen/> :
null}
</div>
);
};
kotlin
when expression
val App = FC {
// ...
div {
// ...
when (gameState) {
GameState.Start -> StartScreen()
GameState.Playing -> PlayingScreen()
GameState.Win -> WinScreen()
GameState.Dead -> EndScreen()
}
}
}
– Both languages support object destructuring
– Within blocks and in lambda parameters
– However, Kotlin’s is limited
– Supported via componentN methods
– Fixed order to properties extracted
– Data classes do this automatically
destructuring
typescript > kotlin
const {value, color} = brick;
const {value, location} = brick;
Arbitrary properties extracted
export const Brick: FC<Props> = ({index}) => {
}
Destructuring on parameters
const [first, ...remaining] = bricks;
Array destructuring
conclusion
they’re both very good
but in different ways
Community
Coroutines
JSX vs React DSL
Multiplatform
Advanced Type System
Extensions
Interop with JS
Expressions
Destructuring
Standard Library
Tooling
Functions
favour stable engineering
Questions?
TypeScript Vs. KotlinJS

TypeScript Vs. KotlinJS

  • 2.
    © Instil Software2020 TypeScript vs KotlinJS should you make the switch?
  • 3.
  • 4.
  • 5.
    – TS bringstypes and compilation to JS – Improves upon the existing strengths of JS – Makes us more productive and happy – Leverages existing JS frameworks – Interop with JS is a design goal we love typescript it solves real problems for us
  • 6.
    – Kotlin improvesupon Java in many ways – Adds null safety, DSLs, coroutines etc... – Makes us more productive and happy – Leverages existing JVM frameworks – But interop with Java is a design goal we love kotlin it solves real problems for us
  • 8.
  • 9.
    experiment: is kotlinjsworth it? – We are not using KotlinJS in production – The code written has been for labs, workshops and talks – Built several apps both TypeScript and KotlinJS – Go beyond “hello world” – Incorporate common JS libraries – Compare the experience – Tooling – Language features – Community what problem does it solve?
  • 10.
  • 11.
    – Template projectfrom IntelliJ – Grade project using Kotlin DSL – Easily integrate NPM packages creating new project the wizard
  • 14.
    multiplatform libraries COMMON KOTLIN KOTLIN ANDROID KOTLINJS KOTLIN NATIVE KOTLIN JVM NATIVE ARTEFACT JS BUNDLE JAR
  • 15.
  • 16.
    configuring the kotlingradle dsl plugins{ kotlin("js")version"1.6.21" kotlin("plugin.serialization")version"1.6.21" } group="org.example" version="1.0-SNAPSHOT" valktorVersion="2.0.2" repositories{ mavenCentral()} dependencies{ ...}
  • 17.
    configuring the kotlingradle dsl kotlin{ js(LEGACY){ binaries.executable() browser{ commonWebpackConfig{ cssSupport.enabled=true } } } } There is a new IR compiler
  • 18.
    tasks in thekotlin gradle dsl
  • 19.
    add multiplatform andkotlinjs packages kotlinjs, multiplatform and npm dependencies { implementation("org.jetbrains.kotlin-wrappers:kotlin-react:17.0.2-pre.290-kotlin-1.6.10") implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:17.0.2-pre.290-kotlin-1.6.10") implementation("org.jetbrains.kotlin-wrappers:kotlin-react-router-dom:6.3.0-pre.340-compat") implementation("org.jetbrains.kotlin-wrappers:kotlin-react-css:17.0.2-pre.290-kotlin-1.6.10") implementation(npm("bootstrap", "4.6.0")) implementation(npm("jquery", "1.9.1- 3")) implementation(npm("popper.js", "^1.16.1")) }
  • 20.
    what’s the codelike standard main function funmain() { valcontainer= document.createElement("div") document.body!!.appendChild(container) valapp=App.create() render(app,container) }
  • 21.
    what’s the codelike easy access to browser apis funmain() { valcontainer= document.createElement("div") document.body!!.appendChild(container) valapp=App.create() render(app,container) }
  • 22.
    what’s the codelike easy access to react library valApp=FC<Props>("Application"){ BrowserRouter{ div{ p{ Link{ to="/hello”+"SimpleComponent”}} } div{ Routes{ Route{ // … } } } }
  • 23.
  • 24.
    its popularity continuesto grow rising star on language rankings … 18 Kotlin … https://redmonk.com/sogrady/2021/03/01 /language-rankings-1-21/ The RedMonk Programming Language Rankings: January 2021
  • 25.
    its popularity continuesto grow rising star on language rankings https://insights.stackoverflow.com/survey/2020 Stack Overflow Developer Survey 2020 Most Used Language 13th Kotlin 1st JavaScript 8th TypeScript
  • 26.
    its popularity continuesto grow loved by its users https://insights.stackoverflow.com/survey/2020 Stack Overflow Developer Survey 2020 Most Loved Language 2nd TypeScript 4th Kotlin 10th JavaScript 1st Rust
  • 27.
    TS is thelargest alternative to JS https://2021.stateofjs.com/en-US/
  • 28.
    – TypeScript ismore popular than KotlinJS – As a superset of JS, reusing knowledge and assets is easier – And the transition for JS developers to TS is easier – TypeScript is well established in the JavaScript world – Many libraries include TypeScript definitions – DefinitelyTyped contains many more community, maturity and support typescript > kotlin
  • 29.
  • 30.
    – Only afew first class wrappers provided – It is easy to add NPM packages yourself – But how easy is it to consume that code in Kotlin? importing npm js packages gradle dsl dependencies { . . . implementation(npm("react-three-fiber", "4.2.20")) implementation(npm("react-use-gesture", "7.0.15")) implementation(npm("three", "0.119.1")) }
  • 31.
    really easy external declarations @file:JsModule("react-three-fiber") @file:JsNonModule ... externalval Canvas: RClass<RProps> external fun extend(objects: Any) external fun useFrame(callback: (dynamic, Double) -> Unit) external fun useThree(): dynamic external interface PointerEvent { val uv: Vector2 } Specify the NPM package Define any items you wish to use
  • 32.
    – Converts TypeScriptd.ts files to Kotlin external declarations – Still experimental – At time of writing, on hold until IR compiler stabilises dukat automatic generation https://kotlinlang.org/docs/js-external-declarations-with-dukat.html
  • 33.
    – Command linetool – Installable in isolation via npm – Simply point to a .d.ts file and it will do the rest dukat usage $ dukat index.d.ts index.module_my-library.kt $ npm install dukat
  • 34.
    dukat export function getString():string; export function setString(input: string): void; external fun getString(): String external fun setString(input: String)
  • 35.
    – Integrated intoGradle – Generates definitions for configured packages dukat usage Dukat tasks ----------- generateExternals generateExternalsIntegrated
  • 36.
    dukat export interface BasicInterface{ readonly field1: number; method1(): boolean; } export function buildInterface(): BasicInterface; export type ReadOnlyBasicInterface = Readonly<BasicInterface>; external interface BasicInterface { var field1: Number fun method1(): Boolean } external fun buildInterface(): BasicInterface typealias ReadOnlyBasicInterface = Readonly<BasicInterface>
  • 37.
    – It’s agood help but has issues – Limited by differences in the languages – Not a seamless workflow – This situation may improve as the tool and Kotlin evolves not a silver bullet square peg and a round hole
  • 38.
    – KotlinJS supportsa dynamic type – You can use it in place of any type – Assign it a value of any type – Access and use members with any name – Basically switches off type checking – This can be used to quickly patch over APIs dynamic get out of jail type external fun useFrame(callback: (dynamic, Double) -> Unit)
  • 39.
    – Object literalsare common in JavaScript – KotlinJS has a helper function to create objects – This is strongly typed (inferred) but requires fields to be var jso object literals in kotlinjs Block(jso { position = brick.location.toVector3() color = brick.color })
  • 40.
    – We canembed JavaScript directly with the js function – The code can even use Kotlin variables – Must be a compile time constant – Cannot be a runtime evaluated expression js embedding javascript private fun getToken(): String? { val tokenKey = TokenKey return js(""" localStorage.getItem(tokenKey) """) }
  • 41.
    – As asuperset, TypeScript has to win this one – The type system is geared to support JavaScript – Lots of libraries already provide TypeScript definition files – However, writing external declaration in KotlinJS is easy – Dukat exists but has fundamental limitations – You may have to write custom translation code on top interop with javascript typescript > kotlinjs
  • 42.
  • 43.
    JSX IN TYPESCRIPT JSX embeds markup insideJS / TS code export const TaskItem: FC<Props> = (props) => <tr key={props.taskIndex}> <td>{props.task.text}</td> <td> <span onClick={props.onToggle}> {pickIcon(props.task.done)} </span> </td> </tr>
  • 44.
    val TaskItem= functionalComponent<TaskItemProps>("TaskItem"){props -> tr{ td { +props.task.text } td { span { +pickIcon(props.task.done) } attrs { onClickFunction= { props.onToggle() } } } } } fun RBuilder.TaskItem(task: Task) = child(TaskItem) { attrs { this.task = task } } REACT DSL IN KOTLIN In Kotlin a DSL provides equivalent functionality
  • 45.
    kotlin DSL’s arevery cool a major advantage
  • 46.
    val TaskItem= functionalComponent<TaskItemProps>("TaskItem"){props -> tr{ td { +props.task.text } td { span { +pickIcon(props.task.done) } attrs { onClickFunction= { props.onToggle() } } } } } fun RBuilder.TaskItem(task: Task) = child(TaskItem) { attrs { this.task = task } } REACT DSL IN KOTLIN JSX is clearly a lot simpler / shorter
  • 47.
    Then they rewroteit (without telling anyone)
  • 49.
    val TaskItem=FC<TaskItemProps>("TaskItem"){props-> tr{ td{ +props.task.text} td{ onClick={props.onToggle()} span{ +pickIcon(props.task.done) } } } } REACT DSL IN KOTLIN
  • 50.
    val TaskItem=FC<TaskItemProps>("TaskItem"){props-> tr{ td{ +props.task.text} td{ onClick={props.onToggle()} span{ +pickIcon(props.task.done) } } } } REACT DSL IN KOTLIN Builder functions not required Many attributes are cleaner attrs section is gone
  • 51.
    The typing is... imperfect
  • 52.
    interface InputHTMLAttributes<T> extendsHTMLAttributes<T> { max?: number | string; min?: number | string; value?: string | ReadonlyArray<string> | number; ... } Type union type PropsWithChildren<P> = P & { children?: ReactNode }; Type intersection
  • 53.
    // Type exportserased! external fun interfaceUnionInput(input: First) external fun interfaceUnionInput(input: Second) external fun interfaceUnionOutput(): dynamic /* First | Second */ export type InterfaceUnion = First | Second; export function interfaceUnionInput(input: InterfaceUnion): void; export function interfaceUnionOutput(): InterfaceUnion; Kotlin supports proper overloads Not supported on the return type
  • 54.
    external fun interfaceIntersectionInput(input:First /* First & Second */) external fun interfaceIntersectionOutput(): First /* First & Second */ export type InterfaceIntersection = First & Second; export function interfaceIntersectionInput(input: InterfaceIntersection): void; export function interfaceIntersectionOutput(): InterfaceIntersection; Intersection dropped
  • 55.
    mapped and conditionaltypes even more power in typescript type Readonly<T> = { readonly [P in keyof T]: T[P]; }; type PromiseType<T extends Promise<any>> = T extends Promise<infer U> ? U : never; Type conditional
  • 56.
    The languages aresimply not fully compatible
  • 57.
    manual workarounds useEffect function useEffect( effect:EffectCallback, deps?: DependencyList ): void; type EffectCallback = () => (void | Destructor); type Destructor = () => void;
  • 58.
    useEffect union return workaround funuseEffect( dependencies: RDependenciesList? = null, effect: () -> Unit ) { // ... } fun useEffectWithCleanup( dependencies: RDependenciesList? = null, effect: () -> Rcleanup ) { // ... }
  • 59.
    useEffect or other patterns useEffect{ } useEffect(dep1, dep2) { } useEffectOnce { } useEffectOnce { cleanup { // Clean up logic goes here } }
  • 60.
    – Kotlin’s DSLsupport is a powerful general purpose tool – But JSX is a single purpose solution that suits React better – TypeScript’s advanced type system is very powerful – Union, intersection and mapped types bring sanity to JS – Kotlin types (unsurprisingly) sit awkwardly on top of JS jsx vs dsl typescript > kotlin
  • 61.
    async await vscoroutines Round 4
  • 62.
    asynchronous programming – Asyncawait is a good async solution in JS & TS – Engineered so it interops with Promises – Succinct promises and async/await async function loadMap(url: string): Promise<void> { const response = await fetch(url); const map = await response.text(); // ... }
  • 63.
    coroutines – Kotlin’s moregeneral coroutines are better – Works with other patterns than simply async – In KotlinJS, it works easily with Promises kotlin > typescript suspend fun loadMap(url: String) { val response = window.fetch(url).await() val map = response.text().await() // ... }
  • 64.
    coroutines – Coroutines aremore general and powerful – They can be used with other patterns too – With suspend functions we don’t need to “await” kotlin > typescript suspend fun loadMap(url: String) { val map = client.get<String>(url) // ... } Ktor Client
  • 65.
    coroutines – Coroutines canbe applied to other patterns too kotlin > typescript fun infinite() = sequence { var count = 0 while (true) { yield(count++) } }
  • 66.
  • 67.
    – Kotlin doesn’thave the ternary, but has more – when for basic pattern matching – if and when are expressions – Unit instead of void – Expression bodied functions – This creates more symmetry in code expressions kotlin > typescript
  • 68.
    typescript chained ternaries const App:FC = () => { // ... return ( <div> // ... {gameState === GameState.Start ? <StartScreen/> : gameState === GameState.Playing ? <PlayingGame/> : gameState === GameState.Dead ? <DeathScreen/> : gameState === GameState.Win ? <WinScreen/> : null} </div> ); };
  • 69.
    kotlin when expression val App= FC { // ... div { // ... when (gameState) { GameState.Start -> StartScreen() GameState.Playing -> PlayingScreen() GameState.Win -> WinScreen() GameState.Dead -> EndScreen() } } }
  • 70.
    – Both languagessupport object destructuring – Within blocks and in lambda parameters – However, Kotlin’s is limited – Supported via componentN methods – Fixed order to properties extracted – Data classes do this automatically destructuring typescript > kotlin
  • 71.
    const {value, color}= brick; const {value, location} = brick; Arbitrary properties extracted export const Brick: FC<Props> = ({index}) => { } Destructuring on parameters const [first, ...remaining] = bricks; Array destructuring
  • 72.
  • 73.
    they’re both verygood but in different ways
  • 74.
    Community Coroutines JSX vs ReactDSL Multiplatform Advanced Type System Extensions Interop with JS Expressions Destructuring Standard Library Tooling Functions
  • 75.
  • 76.

Editor's Notes

  • #6 Lots to love in JavaScript – ubiquitous, popularity/community, succinct syntax, object literals, destructuring But it’s dynamic typing. I’m a fan of static typing
  • #7 Lots to love in JavaScript – ubiquitous, popularity/community, succinct syntax, object literals, destructuring But it’s dynamic typing. I’m a fan of static typing
  • #21 Emphasize how good it is you can start writing code
  • #22 Emphasize how good it is you can start writing code
  • #23 Emphasize how good it is you can start writing code
  • #26 Ask the question – top spot?
  • #27 Ask the question – top spot?
  • #38 TypeScript is more capable when it comes to type programming Not easy to integrate customisations (which are common) If kotlin evolves to support more TS features, less customisation will be necessary
  • #42 More libraries may come out
  • #45 We can trim it down but grouping closing braces We could also group params but So first off, THIS IS PRETTY COOL that we can do this
  • #47 We can trim it down but grouping closing braces We could also group params but So first off, THIS IS PRETTY COOL that we can do this
  • #50 Cumberbatch for cumbersome
  • #51 Cumberbatch for cumbersome
  • #54 Union done as overloads – good! Output simply dynamic - bad
  • #58 It’s not to say you can achieve the desired behaviour