type Example = {
a: string,
b: number
}
let value: Example = {
a: 'hello',
b: 10,
}
// This IIFE is because typescript will narrow the type if assigned directly like
// const k: keyof Example = 'a'
const k = ((): keyof Example => 'a')()
value = {
...value,
// Obviously this is unsound
[k]: 5,
}
即使在严格模式下也能通过。 游乐场链接。
为什么打字稿在这里不健全?我想了解总体的不合理性,这样我就可以避免使用这样不类型安全的模式。如果有任何相关文档或 GitHub 问题,我也将不胜感激。
这是 TypeScript 的一个已知问题,记录于 microsoft/TypeScript#38663。如果您有一个类型为 union 的 计算属性名称,则 TypeScript 会将该类型一直扩展为
string
(请参阅 microsoft/TypeScript#13948),然后或多或少会忽略该属性完全。 也就是说,它比可能将 number
分配给 a
更糟糕,它可以将 任何东西 分配给 a
,包括 false
(请参阅这个游乐场链接)。
目前尚未将其归类为错误,可能是因为属性写入的这种不健全性渗透到了语言中:
// widen the type of value, this is considered "safe"
const myVal: { [k: string]: string | number } = value;
// but oops:
myVal.b = "oopsieDoodle";
修复此类不健全之处会让事情变得更安全,但使用起来可能会更烦人,正如对 microsoft/TypeScript#30769 的许多抱怨所证明的那样。 TypeScript 并不健全,主要是在 TS 团队认为治愈方法比疾病本身更糟糕的地方。请参阅 TypeScript 语言设计非目标 #3 和 TS 团队评论于 microsoft/TypeScript#9825。