TypeScript:提取处理对象数值类型键的函数实现报错解决
TypeScript:处理对象数字类型键的函数类型错误修复
问题描述
现有如下接口:
interface MyObject { mandatoryNumber: number; optionalNumber?: number; mandatoryString: string; optionalString?: string; }
需要编写一个函数,接收该接口的实例,以及一个仅对应number或可选number类型的键。如果键对应的值存在,返回其两倍;否则返回0。
尝试的代码如下,但出现TypeScript错误:Type 'K' cannot be used to index type 'MyObject':
type NumberKeys<T> = { [K in keyof T]: T[K] extends number ? K : never }[keyof T]; function process<K extends NumberKeys<MyObject>>(obj: MyObject, key: K): number { const value = obj[key]; // -> Typescript error: Type 'K' cannot be used to index type 'MyObject' return value !== undefined ? value * 2 : 0; }
错误原因
- 类型工具
NumberKeys逻辑缺陷:对于可选number属性(比如optionalNumber?: number),其类型是number | undefined,T[K] extends number会返回false——因为number | undefined并不严格继承number。这导致NumberKeys<MyObject>实际仅包含"mandatoryNumber",不符合需要包含可选number键的需求。 - 索引类型推断问题:即便修正类型工具,TypeScript仍可能无法自动推断
obj[key]的类型为number | undefined,从而抛出索引错误。
解决方案
方案1:修正类型工具并补充类型断言
先修复NumberKeys,让它能匹配所有值为number或可选number的键:
type NumberKeys<T> = { [K in keyof T]: Exclude<T[K], undefined> extends number ? K : never }[keyof T];
这里用Exclude<T[K], undefined>剔除可选属性的undefined类型,再判断是否继承number,这样可选number键也会被纳入结果。
然后修改函数,通过类型断言明确obj[key]的类型:
function process<K extends NumberKeys<MyObject>>(obj: MyObject, key: K): number { const value = obj[key] as number | undefined; return value !== undefined ? value * 2 : 0; }
方案2:直接限定键类型(更简洁)
如果不需要通用复用NumberKeys类型,也可以直接在函数参数里明确允许的键:
function process( obj: MyObject, key: "mandatoryNumber" | "optionalNumber" ): number { const value = obj[key]; return value !== undefined ? value * 2 : 0; }
方案3:利用空值合并运算符简化代码
结合修正后的NumberKeys,可以用??空值合并运算符简化返回逻辑:
type NumberKeys<T> = { [K in keyof T]: Exclude<T[K], undefined> extends number ? K : never }[keyof T]; function process<K extends NumberKeys<MyObject>>(obj: MyObject, key: K): number { return (obj[key] ?? 0) * 2; }
内容的提问来源于stack exchange,提问作者quentinadam
相关产品推荐
相关产品推荐

