TypeScript映射类型keyof返回string|number问题咨询
问题解答
1. number类型的来源
这不是TypeScript的Bug,是官方有意的设计行为,根源在于JavaScript的对象键处理规则:
- 在JS中,所有对象键最终都会被隐式转换为字符串类型。比如写
obj[123],实际等价于obj["123"]。 - TypeScript为了兼容这种JS原生行为,当你使用字符串索引签名
{ [key: string]: string }时,keyof会同时包含string和number类型——毕竟数字类型的键在JS里是合法的,只是会被隐式转成字符串,TS需要覆盖这种使用场景。
2. 通用解决方案
方案一:过滤number类型的键
如果你的场景只需要纯字符串键,可以用Exclude工具类型把number从键类型中剔除:
type StrictStringKey<T> = Exclude<keyof T, number>; type Test = StrictStringKey<{ [key: string]: string }>; // Test = string
方案二:修正objectKey函数的类型安全问题
你的objectKey函数存在潜在的类型不匹配问题:Object.keys()在TS中固定返回string[](因为JS对象可能包含超出类型定义的额外键),直接赋值给Array<keyof T>不符合TS的类型规则。可以调整为:
function objectKey<const T extends Record<string, unknown>>(object: T): StrictStringKey<T>[] { return Object.keys(object) as StrictStringKey<T>[]; }
方案三:开启严格编译选项
开启--strict(包含noImplicitAny等一系列严格检查规则),可以让TS在类型不兼容时给出更明确的提示,但无法直接改变keyof对字符串索引签名的处理逻辑。
3. 是否属于TypeScript的Bug?
不属于Bug,这是TS为了兼容JavaScript对象键的隐式转换规则特意做的设计,官方文档中明确说明:字符串索引签名的keyof结果会包含string | number类型。
内容的提问来源于stack exchange,提问作者ST-DDT
相关产品推荐
相关产品推荐

