Kotlin中如何实现类似TypeScript的联合类型(Union types)效果?
Kotlin实现类TypeScript联合类型的务实方案
Kotlin没有原生支持和TS完全一致的、不需要继承关系的匿名联合类型,但是可以根据使用场景选不同成本的实现,完全没必要每次都给Int、String这类基础类型写重复的包装类:
1. 零样板临时场景:直接用Any配合智能类型转换
如果是局部变量、小范围使用的场景,不需要严格的编译期穷尽检查,直接用Any作为类型即可,Kotlin的is判断会自动做智能类型转换,写起来和TS体验几乎没有区别:
var a: Any = "hello" a = 3 // 使用时直接判断类型,不需要手动强转 when (a) { is String -> println("字符串长度:${a.length}") is Int -> println("数字值:$a") else -> error("不支持的类型") }
这个方案的缺点是编译器不会强制你检查所有可能的类型,漏写分支的时候编译期不会报错,但是胜在完全没有额外代码,临时用非常方便。
2. 需要编译期安全:写一次通用泛型密封类,全场景复用
如果需要编译器帮你做分支穷尽检查,又不想每次给基础类型写专属包装,只需要提前写一次通用的联合类型密封接口,后续所有类型组合都能直接用,不需要重复写包装:
// 两类型联合,写一次即可全局复用 sealed interface Union2<out A, out B> { data class A<out A>(val value: A): Union2<A, Nothing> data class B<out B>(val value: B): Union2<Nothing, B> } // 可选:写扩展方法简化分支处理,不用每次写is判断 inline fun <reified A, reified B, R> Union2<A, B>.match( onA: (A) -> R, onB: (B) -> R ): R = when(this) { is Union2.A -> onA(value) is Union2.B -> onB(value) }
使用的时候没有额外样板:
var a: Union2<String, Int> = Union2.A("hello") a = Union2.B(3) // 编译器会强制你处理所有分支,漏写会直接报编译错误 val result = a.match( onA = { "字符串长度:${it.length}" }, onB = { "数字值:$it" } )
如果需要支持3种、4种类型的联合,照着结构加Union3、Union4即可,一次编写全项目复用,根本不需要给Int、String单独写包装类。
3. 函数入参场景:直接用函数重载
如果联合类型只用在函数参数位置,根本不需要额外封装,直接写对应数量的重载函数即可,连类型判断都省了:
fun process(value: String) { println("处理字符串:${value.length}") } fun process(value: Int) { println("处理数字:$value") } // 调用时直接传String/Int都能匹配到正确的实现 process("hello") process(3)
内容的提问来源于stack exchange,提问作者Ben Kosten
相关产品推荐
相关产品推荐

