如何在定位JavaScript时表示多种类型(联合类型)

我想要做的是使用一个泛型类型,可以是其他三种类型之一。

这是一个函数的例子:

fun <T> get(key: String) : T where T: String, T: Number, T: Boolean {} 

上面的代码不起作用,那么我应该怎么做呢?

对于KotlinJS,您可以使用ts2kt将您的TypeScript定义转换为Kotlin。 它确实支持联盟类型,但也许不是所有的情况都是完美的。 在ts2kt中有对unionTypes的测试,这些测试揭示了如何处理它们,并且可以为定位JavaScript平台时手动创建的任何东西做类似的事情。

在第41期的评论中提到了进一步的工作- 增加更好的联盟类型支持 。 最后在主题上至少有一个讨论主题,表明:

在JS和TS中,在大多数情况下,union类型被用作重载的替代,所以在不久的将来,我们将在可能的时候使用重载。 另外,我们考虑提供额外的方式来为本地声明指定联合类型。

还有另一个堆栈溢出问题在谈论这个问题,并给出了一些当前的选择: Kotlin和歧视工会(总和类型) ,其中有答案是所有Kotlin目标平台有效。

特别是对于JavaScript目标,您可以考虑使用dynamic类型 。 我在ts2kt中看到至少有一个使用这种类型的测试用例 。 这个例子从这个TypeScript代码开始:

 declare class Foo type Key = Key2 | number; type Key2 = string | Foo; declare var fooKey: Key; declare function barKey(a: Key|number); declare function barList(a: List<Key>); declare function barArray(a: Key[]); interface Parent { (...children: Key[]): Foo; } 

并使用dynamic生成此Kotlin作为返回类型来代替联合类型; 在其他情况下重载方法签名来处理联合类型( 我添加了一些注释 ):

 external open class Foo // using dynamic in place of union type external var fooKey: dynamic /* String | Foo | Number */ = definedExternally // using method overloading in place of union type external fun barKey(a: String): Unit = definedExternally external fun barKey(a: Foo): Unit = definedExternally external fun barKey(a: Number): Unit = definedExternally // using dynamic in place of union type external fun barList(a: List<dynamic /* String | Foo | Number */>): Unit = definedExternally external fun barArray(a: Array<dynamic /* String | Foo | Number */>): Unit = definedExternally external interface Parent { // using method overloading in place of union type @nativeInvoke fun invoke(vararg children: String): Foo @nativeInvoke fun invoke(vararg children: Foo): Foo @nativeInvoke fun invoke(vararg children: Number): Foo } 

但是,您应该再次查看联合类型的所有ts2kt测试用例,以查看包括处理undefined其他想法。

这是行不通的,因为T不能表示为StringNumberBoolean的交集。

如果你想限制你的类型到一个预定义的类型列表,密封类是一个很好的soltuion。

 sealed class MyData { class Bool(val data: Boolean) : MyData() class String(val data: String) : MyData() class Number(val data: Number) : MyData() } fun get(key: String): MyData = TODO() 

编译器如何知道在这种情况下返回哪种类型? T可能是任何东西,所以他们将无法定义这样的东西。

你可以定义三种类型特定的方法:

 fun getString(key: String): String = ... fun getBoolean(key: String): Boolean= ... fun getInt(key: String): Int = ... 

(或者像kevinmost建议的封装方法)