我偶然发现了结构类型的一个局限性,想知道是否有办法绕过它。
假设我有一个如下的类型层次结构:
type Message = HelloMessage | GoodbyeMessage
type HelloMessage = {
message: string
}
type GoodbyeMessage = {
message: string
}
并且我们定义一些类型保护如下:
function isHello(value: any): value is HelloMessage {
return !!value && !!value.message && typeof value.message === "string" && value.message.includes("hello")
}
function isGoodbye(value: any): value is GoodbyeMessage {
return !!value && !!value.message && typeof value.message === "string" && value.message.includes("goodbye")
}
试图在函数中使用类型保护会导致编译器将后续使用类型指定为never
:
function someFunc(input: Message): string {
if (isHello(input)) {
return input.message
}
if (isGoodbye(input)) {
return input.message // compiler errors here
}
return "unknown"
}
一些明显的解决方案是在if
语句中将输入键入为any
或将input
强制转换为GoodbyeMessage
,但这两种方法都不太优雅,这仅仅是Typescript的type
结构特性的限制,还是可以使用其他魔法使其按我所期望的方式工作?
1条答案
按热度按时间6ie5vjzr1#
你是对的,这是类型系统的一个局限性,即使类型保护起作用了,你也不能 * 实际上 * 分辨出一个函数传递的是
HelloMessage
还是GoodbyeMessage
,因为它看到的只是{ message: string }
,你可以使用一个带标记的联合类型,可以用类型保护来区分它: