我正在尝试访问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
的索引签名。
但是,如果我们在编译时知道key
在object
中,当我们进入返回语句时,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
,以防止原型污染。