TypeScript中遍历对象已知属性键出现索引类型错误如何解决?
错误原因
TypeScript 中Object.keys()返回值的类型固定为Array<string>,而你定义的points对象是明确限定了仅包含a/b/c/d/e几个属性,没有声明可接受任意字符串作为键的索引签名。当你尝试用string类型的变量作为索引访问points属性时,TS 无法确定该变量一定是points的合法属性,为了保证类型安全就会抛出此错误。
虽然你可以明确感知到遍历的键都属于points的合法属性,但 TS 的类型系统默认不会做这个推导——因为 JavaScript 允许给对象额外添加未声明属性是合法操作,TS 无法保证运行时item.points上没有其他额外的字符串键。
解决方案
你可以根据自己的业务场景选择以下任意一种方案解决问题:
- 方案1:对key做类型断言
直接告诉 TypeScript 遍历的key一定是points的合法属性,修改遍历行即可:
keys.forEach((key) => { // 用as断言key是points的合法属性,??0处理可选属性为undefined的情况 sum += item.points[key as keyof Siswa['points']] ?? 0 });
keyof Siswa['points']会自动推导得到points所有合法键的联合类型:"a" | "b" | "c" | "d" | "e",类型断言后TS就会认可索引的合法性。
- 方案2:给points添加索引签名
如果后续points可能扩展其他数字类型的属性,可以直接在类型定义中添加索引签名:
interface Siswa { name: string, // 声明points可以接受任意字符串作为键,值类型为数字或undefined points: { [key: string]: number | undefined, a: number, b: number, c: number, d?: number, e?: number } }
声明后TS就允许你用任意字符串类型的变量作为索引访问points的属性,不会再报类型错误。
- 方案3:直接遍历属性值避开key的类型问题
你可以直接用Object.values()获取points的所有属性值求和,不需要处理key的类型校验,代码更简洁:
function find_average_points(data: Array<Siswa>): Array<{name: string, average: number}> { return data.map(item => { // 直接遍历值求和,??0处理可选属性为undefined的情况 const sum = Object.values(item.points).reduce((prev, curr) => prev + (curr ?? 0), 0); const average = sum / Object.keys(item.points).length; return { name: item.name, average } }) }
内容的提问来源于stack exchange,提问作者riki yudha
相关产品推荐
相关产品推荐

