为何Partial Record的Object.values会出现undefined类型?
Partial<Record<string, number>> 取值类型推断问题解析
问题原因
Partial<Record<string, number>>的作用是把Record<string, number>的所有属性标记为可选,这意味着每个键对应的值类型变成了number | undefined。TypeScript是静态类型检查工具,只会依据类型定义做推断,不会分析你运行时实际给对象赋了哪些值。所以调用Object.values()时,类型系统默认认为每个值都可能是undefined,最终推断出的类型就是(number | undefined)[]——哪怕你实际给所有键都赋了确定的number值。
规避方法
1. 类型断言(简单直接,需自行保证数据安全)
直接把结果断言为number[],前提是你能确保对象里没有undefined值:
const obj: Partial<Record<string, number>> = { a: 1, b: 2 }; const values = Object.values(obj) as number[]; // 类型为number[]
2. 运行时类型守卫(更安全)
写一个类型守卫函数,在运行时检查数组中是否存在undefined,通过检查后TypeScript会自动把类型收窄为number[]:
function isAllNumbers(arr: (number | undefined)[]): arr is number[] { return arr.every(item => typeof item === 'number'); } const obj: Partial<Record<string, number>> = { a: 1, b: 2 }; const values = Object.values(obj); if (isAllNumbers(values)) { // 此处values类型自动推断为number[] console.log(values.map(n => n * 2)); }
3. 替换类型定义(从根源解决)
如果你的对象实际所有键都有确定的number值,没必要用Partial,直接用Record<string, number>定义类型:
const obj: Record<string, number> = { a: 1, b: 2 }; const values = Object.values(obj); // 类型自动为number[]
如果需要先创建一个部分赋值的对象再补全属性,可以先断言为Record<string, number>:
const obj = {} as Record<string, number>; obj.a = 1; obj.b = 2; const values = Object.values(obj); // 类型为number[]
4. 用类型工具提取非undefined值类型
通过Exclude工具类型剔除undefined,再做断言:
type NumValue = Exclude<Partial<Record<string, number>>[string], undefined>; const obj: Partial<Record<string, number>> = { a: 1, b: 2 }; const values = Object.values(obj) as NumValue[]; // 类型为number[]
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

