joseph_ivie
07/31/2025, 2:17 PMtype
.
// expect files only
expect type ViewNode
expect type TextInput: ViewNode
expect val TextInput.content: String
// actual files only
actual typealias ViewNode = HTMLElement // js
actual typealias ViewNode = View // android
actual typealias ViewNode = UIView // ios
actual typealias TextInput = HTMLInputElement // js
actual typealias TextInput = EditText // android
actual typealias TextInput = UITextField // ios
actual fun TextInput.content get() = this.value // js
actual fun TextInput.content get() = this.text // android
actual fun TextInput.content get() = this.text // ios
type
would have no restrictions about what the actual is - it could be a class
, interface
, open class
, or more.
Consequently, you wouldn't be able to use the type for anything other than an input, output, or receiver to a function.Chris Lee
07/31/2025, 2:54 PMConsequently, you wouldn’t be able to use the type for anything other than an input, output, or receiver to a function.You aren’t creating “types” here, only type aliases; any aliases for the same type (and that type itself) are interchangeable. For example, aliasing MyString = String - anywhere that can use a String can use a MyString, and conversely anywhere that uses MyString can take a String. Value classes are the pattern for creating almost-zero-abstraction types where the compiler enforces type safety.
joseph_ivie
07/31/2025, 2:58 PMRuckus
07/31/2025, 3:00 PMjoseph_ivie
07/31/2025, 3:02 PMRuckus
07/31/2025, 3:03 PMRuckus
07/31/2025, 3:05 PMjoseph_ivie
07/31/2025, 3:06 PM// common code
expect typealias ViewNode
expect typealias TextInput: ViewNode
expect fun textInput(): TextInput
expect fun col(setup: ()->Unit): ViewNode
expect fun button(label: String, action: ()->Unit): ViewNode
expect var TextInput.text: String
fun sample() {
col {
val email = textInput()
val password = textInput()
button("submit") {
callApi(email.text, password.text)
}
}
}
Ruckus
07/31/2025, 3:08 PMjoseph_ivie
07/31/2025, 3:08 PMRuckus
07/31/2025, 3:14 PMjoseph_ivie
07/31/2025, 3:18 PMRuckus
07/31/2025, 3:21 PMYoussef Shoaib [MOD]
07/31/2025, 5:25 PM// expect files only
value class ViewNode internal constructor(internal val underlying: Any?)
value class TextInput internal constructor(val viewMode: ViewNode)
expect val TextInput.content: String
// actual files only
fun HTMLElement.toViewNode(): ViewNode = ViewNode(this) // js
val ViewNode.htmlElement get() = underlying as HTMLElement // js
fun View.toViewNode(): ViewNode = ViewNode(this) // android
val ViewNode.view get() = underlying as View // android
fun UIView.toViewNode(): ViewNode = ViewNode(this) // ios
val ViewNode.uiView get() = underlying as UIView // ios
fun HTMLInputElement.toTextInput(): TextInput = TextInput(toViewNode()) // js
val TextInput.htmlInputElement get() = viewMode.htmlElement as HTMLInputElement // js
fun EditText.toTextInput(): TextInput = TextInput(toViewNode()) // android
val TextInput.editText get() = viewMode.view as EditText // android
fun UITextField.toTextInput(): TextInput = TextInput(toViewNode()) // ios
val TextInput.uiTextField get() = underlying as UITextField // ios
actual fun TextInput.content get() = htmlInputElement.value // js
actual fun TextInput.content get() = editText.text // android
actual fun TextInput.content get() = uiTextField.text // ios
Youssef Shoaib [MOD]
07/31/2025, 5:26 PM