function Foo<DataType extends { [_: string]: unknown }>(name: keyof DataType) {
return name;
}
Foo<{"name":"Tom",1:string}>(1); // why is this not an error?
这里发生何事?我认为数字键应该是错误的.
function Foo<DataType extends { [_: string]: unknown }>(name: keyof DataType) {
return name;
}
Foo<{"name":"Tom",1:string}>(1); // why is this not an error?
这里发生何事?我认为数字键应该是错误的.
TypeScript大致将数字键视为special type of string key.
这是因为在JavaScript中,都是非symbol
property keys are coerced to string
.在TypeScript documentation for index signatures中,它略微间接地提到了这一点,因为它提到number
索引签名属性类型必须与string
索引签名兼容:
可以同时支持两种类型的索引器,但从数值索引器返回的类型必须是从字符串索引器返回的类型的子类型.这是因为当使用
number
进行索引时,在索引到对象之前,JavaScript实际上会将其转换为string
.这意味着使用100
(number
)进行索引与使用"100"
(string
)进行索引是相同的,因此两者需要保持一致.
实际上,从TypeScript 2.9开始,当keyof
operator应用于具有string
索引签名的类型时,将返回number
和string
:
type X = keyof { [_: string]: unknown };
// type X = string | number
这并不完全准确或一致,在语言的其他地方也有一些奇怪的边缘情况("1" extends keyof {1: string}
是false,1 extends keyof {"1": string}
也是false,但你可以访问任何类型的对象上的任何一个键:
let k1: keyof { 1: string };
k1 = 1; // okay
k1 = "1"; // error
declare const o1: { 1: string };
o1[1]; // okay
o1["1"]; // okay
let k2: keyof { "1": string };
k2 = 1; // error
k2 = "1"; // error
declare const o2: { "1": string };
o2[1]; // okay
o2["1"]; // okay
但这些都是次要影响.如果你因为某种原因拒绝need个数字键,那么你可以看Forbid number property for string-typed index signature分的问题和答案.