TypeScript中Object.values()无法从Record联合类型推导正确类型怎么办?
TypeScript中Object.values()从Record联合类型推导正确类型的解决方案
问题场景
当使用Object.values()处理Record类型的联合时,TypeScript无法自动推导出正确的数组类型:
type A = Record<string, number>; type B = Record<string, boolean>; function func(value: A | B) { const properties = Object.values(value); // 实际类型为any[],期望是number[] | boolean[] }
解决方案
1. 使用类型守卫区分联合类型
通过自定义类型守卫明确判断输入类型,让TypeScript能正确推导Object.values()的返回值:
type A = Record<string, number>; type B = Record<string, boolean>; // 类型守卫:判断是否为A类型 function isA(value: A | B): value is A { // 处理空对象情况,若需兼容空对象可额外添加判断逻辑 const firstValue = Object.values(value)[0]; return typeof firstValue === 'number'; } function func(value: A | B) { let properties: number[] | boolean[]; if (isA(value)) { properties = Object.values(value); // 类型为number[] } else { properties = Object.values(value); // 类型为boolean[] } }
2. 自定义泛型工具函数
封装泛型函数,利用类型推断直接返回对应类型的数组:
type A = Record<string, number>; type B = Record<string, boolean>; // 泛型函数:提取Record的值类型组成数组 function getValues<T extends Record<string, infer U>>(obj: T): U[] { return Object.values(obj) as U[]; } function func(value: A | B) { const properties = getValues(value); // 类型为number[] | boolean[] }
3. 扩展Object.values的全局类型定义
通过全局声明扩展Object.values的类型,使其支持联合Record类型的推导:
declare global { interface ObjectConstructor { values<T extends Record<string, unknown>>(obj: T): T[keyof T][]; } } type A = Record<string, number>; type B = Record<string, boolean>; function func(value: A | B) { const properties = Object.values(value); // 类型为number[] | boolean[] }
方案说明
- 类型守卫方案适合需要明确分支逻辑的场景,但需注意空对象等边界情况的处理;
- 泛型工具函数方案简洁,仅在局部生效,不会影响全局类型;
- 全局类型扩展方案会改变项目中所有
Object.values的类型推断行为,需根据项目实际情况谨慎使用。
内容的提问来源于stack exchange,提问作者Serhii Holinei
相关产品推荐
相关产品推荐

