如果条件"对象中的属性"为真,为什么 TypeScript 不推断对象 [属性] 的类型是对象值的联合类型?



我正在尝试访问object[property],而TypeScript抛出element implicitly has any type错误。

const getValue = (key: string) => {
const object = {
property0: 14
property1: -3
}
if (!(key in object)) {
throw new Error(`Invalid key: ${key}`)
}
return object[key]
} 

如果我们不知道property in object是否为真,我们必须自己为TypeScript提供索引签名。也就是说,如果我们从该函数中删除了if(!(key in object))条件,TypeScript应该抛出一个错误,直到我们手动注意到object的索引签名。

但是,如果我们在编译时知道keyobject中,当我们进入返回语句时,TypeScript应该不会为这个函数抛出这样的错误,而应该将getValue的返回类型推断为number

我可以通过手动注意object的索引签名来解决这个问题:

interface ObjectWithOnlyNumberProperties {
[key: string]: number
}
const getValue = (key: string) => {
const object: ObjectWithOnlyNumberProperties = {
property0: 14
property1: -3
}
if (!(key in object)) {
throw new Error(`Invalid key: ${key}`)
}
return object[key]
} 

但似乎我不应该这样做,并且object[key]的类型应该在编译时可推断为typeof property0 | typeof property1,因为我们知道key in object为真。

复制Romain Laurent的评论,完美地回答了这个问题!

在编译时,TypeScript处理的是类型,而不是实际的对象。缺省情况下,{ property0: 14, property1: -3 }的类型为{ property0: number, property1: number }。TypeScript中的类型是A最小契约一致性,所以就TypeScript所知,{ property0: number, property1: number }类型可以引用一个实际的对象,如{ property0: 14, property1: -3, property2: "string" }。显然,我们在代码中知道它不会,但TypeScript不会知道。如上例所示,object[property]为类型any,因为property2可以是任何类型,而不仅仅是string

更新:根据geoffrey的评论,如果你使用的是目标库es2022或更高版本,你也应该更新上面的代码,使用Object.hasOwn(object, property)而不是property in object,以防止原型污染。

相关内容

  • 没有找到相关文章

最新更新