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索引签名的类型时,将返回numberstring:

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分的问题和答案.

Playground link to code

Typescript相关问答推荐

Tailwind CSS样式不在Svelte应用程序中呈现

脉轮ui打字脚本强制执行图标按钮的咏叹调标签-如何关闭

TS 2339:属性切片不存在于类型DeliverableSignal产品[]上>'

使用前的组件渲染状态更新

参数类型undefined不能分配给参数类型字符串|未定义

HttpClient中的文本响应类型选项使用什么编码?''

在泛型类型中对子代执行递归时出错

使用泛型keyof索引类型以在if-condition内类型推断

如何在编译时为不带常量的参数引发错误

在Typescript 中,有没有`index=unfined的速记?未定义:某个数组[索引]`?

Cypress页面对象模型模式.扩展Elements属性

以Angular 自定义快捷菜单

如何通过TypeScrip中的函数防止映射类型中未能通过复杂推理的any值

确保对象列表在编译时在类型脚本中具有唯一键

我在Angular 17中的environment.ts文件中得到了一个属性端点错误

tailwind css未被应用-react

使用ngfor循环时,数据未绑定到表

如何使用angular15取消选中位于其他组件中的复选框

TypeScript是否不知道其他函数内部的类型判断?

广义泛型类型不加载抽象类型上下文