问题
Below syntax,
interface StringArray {
[index: number]: string;
}
states that when a StringArray
is indexed with a number
, it will return a string
. For example - let myArray: StringArray;myArray = ["Bob", "Fred"];let myStr: string = myArray[0];
So, myArray
is type constrained on values stored as string
type, by declaring it with type StringArray
. Key(index) is always string
type, under the hood(JavaScript), despite mentioning it as number
From the below syntax,
class Animal{
name: string;
}
class Dog extends Animal{
breed: string;
}
interface NotOkay {
[x: number]: Animal;
[x: string]: Dog;
}
1) What does NotOkay
syntax state?
From the below syntax,
interface NumberDictionary {
[index: string]: number;
length: number; // ok, length is a number
name: string; // error, the type of 'name' is not a subtype of the indexer
}
2) What does NumberDictionary
state?
3) Why these two syntax are wrong? error TS2413
& error: TS2411
回答1:
(as @betadeveloper points out, the examples are taken from the typescript documentation at https://www.typescriptlang.org/docs/handbook/interfaces.html)
1+3) The point the documentation is making is that this declaration is not consistent.
The declaration would seem to say that this code works:
let no: NotOkay
function byString(key: string): Dog {
return no[key]
}
function byNumber(key: number): Animal {
return no[key]
}
But the problem is that a lookup of e.g. no[0]
is really the same things as no['0']
(it's how JavaScript works). So byString('0')
will actually just result in an Animal, not necessarily a Dog.
So to prevent the code above – that looks correct but is in fact wrong for certain string keys (those that happen to be numbers in string form) – TypeScript does not allow the declaration.
2+3) [index: string]: number;
says that you can use any string as an index of a NumberDictionary
and you will get a number.
On the other hand, name: string;
says that the property name
is a string. But a property can also be accessed as an index, so e.g. when doing
let nd: NumberDictionary
let a = nd['name']
let b = nd.name
a and b mean exactly the same thing, but the first declaration seemed to say a
was a number, whereas the second declaration seems to say b
is a string. That's a contradiction and therefore this declaration is also not allowed.
来源:https://stackoverflow.com/questions/47487415/indexable-type-typescript