TypeScript自定义类型string索引报错且无法限制多余属性如何解决
问题根因
TypeScript 中 Object.keys() 函数的返回值类型被设计为 string[],而非 Array<keyof 输入对象类型>,这是因为运行时对象可能包含类型定义外的额外属性,TS 为了类型安全没有做更窄的推导,所以直接用返回的 string 类型 key 访问严格定义的 Report 类型对象时会触发 7053 错误。
而你尝试添加 string 索引签名的方案会破坏原类型的多余属性校验,不可取。
可行方案
不需要修改原 Report 类型定义,保留原有严格的字段限制即可,只需要处理遍历逻辑的类型:
// 原类型保持不变,依然会校验必填字段、禁止多余属性 type Report = { branches: number; // 该字段必填 functions: number; // 该字段必填 lines: number; // 该字段必填 statements: number; // 该字段必填 }; const report: Report = { branches: 10, functions: 19, lines: 54, statements: 67, }
方案1:单次使用时直接做类型断言
遍历的时候给 Object.keys 的返回值做类型断言,明确告知 TS 这里的 key 都是 Report 的合法属性:
const items = (Object.keys(report) as Array<keyof Report>).map(key => report[key])
方案2:封装通用工具函数复用
如果多处需要类似遍历逻辑,可以封装通用的 keys 提取函数,避免重复写断言:
// 通用工具函数,传入任意对象,返回类型为该对象合法键的数组 function getTypedKeys<T extends object>(obj: T) { return Object.keys(obj) as Array<keyof T> } // 使用时直接调用即可 const items = getTypedKeys(report).map(key => report[key])
效果验证
- 多余属性校验正常生效:如果给 Report 类型的变量赋值带多余字段的对象字面量,TS 会正常抛出错误,比如你例子中的
imABug字段会被拦截。 - 遍历逻辑无类型错误:通过类型断言后,TS 可以识别 key 的合法类型,不会再触发 7053 报错。
注:TypeScript 的多余属性校验仅针对直接赋值给带类型标注变量的对象字面量,如果是先定义一个带额外属性的变量再赋值给 Report 类型变量,属于 TS 设计上的类型兼容性允许范围,和本方案无关。
内容的提问来源于stack exchange,提问作者Kirk Strobeck
相关产品推荐
相关产品推荐

