我想让MyInterface.dic
像一个字典name: value
,我定义它如下:
interface MyInterface {
dic: { [name: string]: number }
}
现在我创建一个等待我的类型的函数:
function foo(a: MyInterface) {
...
}
输入:
let o = {
dic: {
'a': 3,
'b': 5
}
}
我期望 foo(o)
是正确的,但编译器正在下降:
foo(o) // TypeScript error: Index signature is missing in type { 'a': number, 'b': number }
我知道有一个可能的转换:let o: MyInterface = { ... }
可以解决问题,但是 为什么 TypeScript 不能识别我的类型?
额外:如果 o
声明为内联,则工作正常:
foo({
dic: {
'a': 3,
'b': 5
}
})
最佳答案
问题是当推断出类型时,那么o
的类型是:
{ dic: { a: number, b: number } }
这与 { dic: { [name: string]: number } }
不同.至关重要的是,使用顶级签名,您不允许执行类似 o.dic['x'] = 1
的操作。 .有了第二个签名,你就是。
它们在运行时是等效的类型(实际上,它们是完全相同的值),但 TypeScript 安全性的很大一部分来自于它们不相同的事实,并且它只会让你处理一个如果它知道它明确地打算作为一个对象,则将对象作为字典。这就是阻止您意外读取和写入对象上完全不存在的属性的原因。
解决方案是确保 TypeScript 知道它打算用作字典。这意味着:
在某处明确提供一个类型,表明它是一个字典:
let o: MyInterface
断言它是一个内联字典:
let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }
确保它是 TypeScript 为您推断的初始类型:
foo({ dic: { 'a': 1, 'b': 2 } })
如果在某些情况下 TypeScript 认为它是一个只有两个属性的普通对象,然后您稍后尝试将它用作字典,它会不高兴。
关于casting - TypeScript:类型中缺少索引签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37006008/