Typescript: Index signature is missing in type

2020-02-23 05:37发布

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

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) // 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, why typescript is not recognizing my type?


Extra: works fine if o is declared inline:

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

1条回答
▲ chillily
2楼-- · 2020-02-23 05:57

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

{ 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.

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.

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

  • 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 } })

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.

查看更多
登录 后发表回答