You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何`keyof Record<string, any>`返回`string`,`keyof {[K:string]:any}`返回`string|number`?

Record与字符串索引签名的差异解析

一、keyof结果不同的核心原因

1. 字符串索引签名({[K:string]: any})的keyof行为

当定义字符串索引签名时,TypeScript会兼容JavaScript的运行时特性:对象的数字键会被自动转换为字符串。因此keyof {[K:string]: any}返回string | number——这是为了适配用数字访问字符串键的场景(比如obj[0]和obj["0"]在运行时完全等价)。

2. Record<K, T>的keyof行为

Record本质是映射类型,官方定义如下:

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

映射类型会严格遍历K的所有类型成员,不会自动扩展范围。当K为string时,映射生成的类型仅包含string类型的键,因此keyof Record<string, any>的结果就是string。

你测试的字面量联合类型例子也能佐证这一点:

type Test = keyof { [K in 'foo' | 'bar' | 'baz']: any } // 'foo' | 'bar' | 'baz'

映射类型完全复用了K的类型集合,没有额外添加其他类型。

二、为什么Record<string, any>允许数字键赋值且能通过数字访问?

这是TypeScript类型兼容性与JavaScript运行时行为结合的结果:

  1. 赋值兼容性:{0: 'test'}在运行时会将数字键0转换为字符串"0",而Record<string, any>允许任意字符串键,因此这个对象符合类型要求,赋值合法。
  2. 数字索引访问:虽然keyof Foo是string,但TypeScript会自动处理数字到字符串的类型转换——在类型层面,数字字面量可以被当作字符串索引的合法输入(因为运行时会自动转成字符串),所以Foo[0]的访问等价于Foo["0"],完全合法。

内容的提问来源于stack exchange,提问作者sheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:42:46