Adam S
07/26/2023, 12:17 PMexternal interface Extension // some external TypeScript interface
// SomeConfig is an external TypeScript interface
// it has a property with a type-union type, but don't implement it as a member...
external interface SomeConfig {
// multiProp: number | string | Extension | ((string) => Extension | null)
}
// instead, implement multiProp as an extension property using a custom delegate, TypeUnion
// and specify the types within the union
val SomeConfig.multiProp by TypeUnion<Int, String, Extension, (String) -> Extension?>()
// example usage
fun foo(config: SomeConfig) {
// thanks to some assignment plugin magic, the types specified in the TypeUnion delegate can be assigned
config.multiProp = 123
config.multiProp = "a b c"
config.multiProp = object : Extension {}
config.multiProp = { arg -> if (arg == "blah") object : Extension {} else null }
config.multiProp = true // ERROR: Boolean is not specified TypeUnion
}
More info in this gist, or full code in threadAdam S
07/26/2023, 12:19 PMAdam S
07/26/2023, 12:21 PMArtem Kobzar
07/26/2023, 12:41 PMAdam S
07/26/2023, 12:50 PMdynamic
and then cast to the correct type.
@AssignmentOverload
sealed class TypeUnionProperty {
protected abstract val owner: dynamic
protected abstract val propertyName: String
// add new function to get read the value:
fun value(): dynamic = owner[propertyName]
}
Adam S
07/26/2023, 12:59 PMsealed interface MultiPropTypeUnion
value class MultiPropInt(val value: Int): MultiPropTypeUnion
value class MultiPropString(val value: String): MultiPropTypeUnion
value class MultiPropExtension(val value: Extension): MultiPropTypeUnion
fun interface MultiPropCustom: MultiPropTypeUnion {
fun select(value: (String)) : Extension
}
and then add a selector lambda to TypeUnionProperty, to be used when returning a value
sealed class TypeUnionProperty<T> {
// ...
protected abstract val selector: (dynamic) -> T?
fun value(): T? = selector(owner[propertyName])
}