I’ve figured out a hot new strat for defining type...
# javascript
a
I’ve figured out a hot new strat for defining type-union properties, so the types within the union can be specified and made typesafe in Kotlin WDYT?
Copy code
external 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 thread
Step 1, apply an activate the Kotlin Assignment Plugin in the build config
Step 2, copy and paste the TypeUnion Kotlin code. (Suggestions on how to fix the hacks are welcome!)
a
Could you please also provide an example how to use the property? I mean, if I would like to pass the property as a parameter of a function
a
that’s a more difficult prospect! Reading the value is possible, but it wouldn’t be typesafe using the generic approach I’ve proposed. So the value would have to be returned as
dynamic
and then cast to the correct type.
Copy code
@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]
}
you could specify a custom sealed type for each property, e.g.
Copy code
sealed 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
Copy code
sealed class TypeUnionProperty<T> {
  // ...
  protected abstract val selector: (dynamic) -> T?

  fun value(): T? = selector(owner[propertyName])
}