- Kotlin's Type-Safe Builders are the most compelling feature useful for React, virtual-dom, Cycle, (think type-safe JSX) which TypeScript doesn't have as far as I know.
- Some minor guards and checks had to be added to Cycle.js core, because Kotlin inserts metadata noise in arbitrary objects.
- Not all types working, used
dynamic
when I didn't have patience/time to figure out the type system. - Kotlin compiler does a bit too much pollution in JS which makes interop with JS libraries such as Cycle.js a bit harder.
- Kotlin feels good, but I haven't used TypeScript to compare them.
- I believe one can make a tool to automate the conversion of TypeScript definition files into Kotlin code with interfaces.
- No CommonJS support still, which sucks, but you can get things done by importing JS libraries with old-style
<script>
.
Last active
May 6, 2024 03:15
-
-
Save staltz/f5ed815dc54c6433d5f8 to your computer and use it in GitHub Desktop.
Cycle giving baby steps into Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlin.browser.document | |
import kotlin.browser.window | |
// Type definitions | |
native("Cycle") | |
val Cycle : dynamic = noImpl | |
native("Cycle.h") | |
fun h(tagName: String) : VTree = noImpl | |
native("Cycle.h") | |
fun h(tagName: String, children: Array<VTree>) : VTree = noImpl | |
native("Cycle.h") | |
fun h(tagName: String, content: String) : VTree = noImpl | |
native("Cycle.makeDOMDriver") | |
fun makeDOMDriver(container: String): () -> Unit = noImpl | |
interface Observable { | |
fun subscribe() | |
fun map(fn: (input: dynamic) -> dynamic): Observable | |
fun startWith(value: dynamic): Observable | |
} | |
interface VTree { | |
val properties : dynamic | |
} | |
interface QueryableObservableCollection { | |
fun get(vararg params: String): Observable | |
} | |
interface DriverResponseCollection { | |
val DOM : QueryableObservableCollection | |
} | |
// Cycle app | |
fun app(drivers: dynamic): dynamic { | |
return object { | |
val DOM = drivers.DOM.get("input", "input") | |
.map({ ev -> ev.target.value }) | |
.startWith("") | |
.map({ name -> | |
h("div", arrayOf( | |
h("input"), h("h2", "Hello $name") | |
)) | |
}) | |
} | |
} | |
// Kotlin main function initializing Cycle app | |
fun main(args: Array<String>) { | |
window.addEventListener("load", { | |
Cycle.run(::app, object { | |
val DOM = makeDOMDriver("#app") | |
}) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A lot of stuff has changed in the past year in the kotlin world. There have been a lot of additions to the JS/web support. I'm an Android developer, and have been following your work, specifically the MVI stuff. I've been applying principles to the android work that I do, and I'm curious to see how you apply kotlin principles to Cycle.js.
I think sealed types (algebraic data types) are a game changer for doing things like stream processing
CommonJS support
Typescript to kotlin converter
React app using kotlin