patterntypescriptCritical
TypeScript: Index signature is missing in type
Viewed 0 times
typescriptindexsignaturemissingtype
Problem
I want
Now I create a function which waits for my type:
And the input:
I'm expecting
I know there is a possible casting:
Extra: works fine if
MyInterface.dic to be like a dictionary name: value, and 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 why is TypeScript not recognizing my type?Extra: works fine if
o is declared inline:foo({
dic: {
'a': 3,
'b': 5
}
})Solution
The problem is that when the type is inferred, then the type of
That's not the same as
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:
-
Asserting it to be a dictionary inline:
-
Ensuring it's the initial type that TypeScript infers for you:
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.
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: { '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.
Code Snippets
{ dic: { a: number, b: number } }Context
Stack Overflow Q#37006008, score: 146
Revisions (0)
No revisions yet.