javascript - 当“联合类型上不存在 Typescript 属性”时无法使用变量进行评估
问题描述
这是对联合类型上不存在 Typescript 属性的后续问题。
提供的解决方案是使用in 运算符评估联合中的任一对象。效果很好!这是示例:
type Obj1 = { message: string }
type Obj2 = { text: string }
const getText = (obj: Obj1 | Obj2): string => {
if ("message" in obj) {
return obj.message
}
return obj.text
}
但是,当我尝试使用变量对其进行评估时,会发生相同的错误:
const getText = (obj: Obj1 | Obj2): string => {
let property = "message"
if (property in obj) {
return obj.message
}
return obj.text
}
我只是错过了一些非常明显的东西吗?
解决方案
Typescript 不相信当键是变量(而不是文字)时,像这样的条件实际上会缩小类型。您可以告诉这一点,因为当您将鼠标悬停在条件分支中的 obj 上时,它会报告一种Obj1 | Obj2
.
看起来编译器应该能够解决这个问题并知道它是安全的,但是 typescript 编译器并不完美。但它的设计目的是偏向悲观主义,因为过度报告问题比让问题溜进生产代码更危险。
这种情况似乎是一个很大的限制。但在实践中,它不会出现太多。您的代码要求该message
属性在该条件下可用。使用变量进行测试没有任何意义,因为为了获得类型安全的代码,它只能是property
. 因此,您不妨在测试中只使用文字字符串。
但是,如果您对此进行了很多测试,并且希望避免一遍又一遍地输入 sam 文字,则可以创建一个简单的可重用类型保护函数来执行此操作:
function isObj1(obj: Obj1 | Obj2): obj is Obj1 {
return 'message' in obj
}
const getText = (obj: Obj1 | Obj2): string => {
if (isObj1(obj)) {
return obj.message
}
return obj.text
}