typescript 打字稿:类型中缺少索引签名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37006008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:06:45  来源:igfitidea点击:

Typescript: Index signature is missing in type

castingtypescript

提问by Manu

I want MyInterface.dicto be like a dictionary name: value, I define it as follows:

我想像MyInterface.dic一本字典name: value,我定义如下:

interface MyInterface {
    dic: { [name: string]: number }
}

Now I create a function which waits for my type:

现在我创建一个等待我的类型的函数:

function foo(a: MyInterface) {
    ...
}

And the input:

和输入:

let o = {
    dic: {
        'a': 3,
        'b': 5
    }
}

I'm expecting foo(o)to be correct, but the compiler is falling:

我希望foo(o)是正确的,但编译器正在下降:

foo(o) // Typescript error: Index signature is missing in type { 'a': number, 'b': number }

I know there is a possible casting: let o: MyInterface = { ... }which do the trick but the question is, whytypescript is not recognizing my type?

我知道有一个可能的转换:let o: MyInterface = { ... }哪个可以解决问题,但问题是,为什么打字稿不能识别我的类型?



Extra: works fine if ois declared inline:

额外:如果o声明为内联,则工作正常:

foo({ 
  dic: {
    'a': 3, 
    'b': 5
  }
})

回答by Tim Perry

The problem is that when the type is inferred, then the type of ois:

问题是,当推断出类型时,则类型o为:

{ dic: { a: number, b: number } }

That's not the same as { dic: { [name: string]: number } }. Critically, with the top signature you're not allowed to do something like o.dic['x'] = 1. With the 2nd signature you are.

这与{ dic: { [name: string]: number } }. 至关重要的是,使用顶级签名,您不能执行类似o.dic['x'] = 1. 有了第二个签名,你就是。

They are equivalent types at runtime (indeed, they're the exact same value), but a big part of TypeScript's safety comes from the fact that these aren't the same, and that it'll only let you treat an object as a dictionary if it knows it's explicitly intended as one. This is what stops you accidentally reading and writing totally non-existent properties on objects.

它们在运行时是等价的类型(实际上,它们是完全相同的值),但是 TypeScript 的安全性很大一部分来自于它们不相同的事实,并且它只会让您将对象视为字典,如果它知道它明确地打算作为一个。这就是阻止您意外读取和写入对象上完全不存在的属性的原因。

The solution is to ensure TypeScript knows that it's intended as a dictionary. That means:

解决方案是确保 TypeScript 知道它是作为字典使用的。这意味着:

  • Explicitly providing a type somewhere that tells it it's a dictionary:

    let o: MyInterface

  • Asserting it to be a dictionary inline:

    let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }

  • Ensuring it's the initial type that TypeScript infers for you:

    foo({ dic: { 'a': 1, 'b': 2 } })

  • 在某处显式提供一个类型,告诉它是一个字典:

    let o: MyInterface

  • 断言它是一个内联字典:

    let o = { dic: <{ [name: string]: number }> { 'a': 1, 'b': 2 } }

  • 确保它是 TypeScript 为您推断的初始类型:

    foo({ dic: { 'a': 1, 'b': 2 } })

If there's a case where TypeScript thinks it's a normal object with just two properties, and then you try to use it later as a dictionary, it'll be unhappy.

如果有一种情况,TypeScript 认为它是一个只有两个属性的普通对象,然后你稍后尝试将它用作字典,它会不高兴。