为什么TypeScript类型守卫在for-in循环中无法断言属性类型?
问题原因与解决办法
你遇到的TS2571错误,核心原因是TypeScript对动态索引访问的类型守卫支持有限。
当函数参数obj的类型是{ [key: string]: unknown }时,循环里的key是动态变化的变量。虽然你用typeof obj[key] === "number"做了类型判断,但TypeScript没办法把obj[key]的类型从unknown缩小到number——因为它无法跟踪每个动态key对应的具体值类型,只能确定当前判断的那一刻值是number,但不会修改整个索引签名的类型推断。
解决办法
最简单的修复方式是先把obj[key]赋值给一个临时变量,再对这个变量做类型守卫:
type Fruit = { [key: string]: number | string; }; const fruits: Fruit = { apple: 1, orange: 3, banana: "yellow", }; function getTotal(obj: { [key: string]: unknown }): number { let total = 0; for (let key in obj) { const value = obj[key]; // 先存到临时变量 if (typeof value === "number") { total += value; // 这里TypeScript能正确识别value是number类型 } } return total; } console.log(getTotal(fruits));
另外,如果你的场景允许,也可以把函数参数类型调整为更精确的{ [key: string]: number | string },这样typeof类型守卫也能直接生效,不需要临时变量:
function getTotal(obj: { [key: string]: number | string }): number { let total = 0; for (let key in obj) { if (typeof obj[key] === "number") { total += obj[key]; } } return total; }
内容的提问来源于stack exchange,提问作者jerome
相关产品推荐
相关产品推荐

