使用Object.keys结合reduce遇TypeScript类型错误,求无封装解决方案
解决TypeScript中Object.keys结合reduce的索引类型错误问题
你碰到的这个问题是TypeScript类型系统里的常见情况——Object.keys()默认返回string[]类型,而不是我们期望的(keyof T)[]。这是因为JavaScript里对象可能存在定义类型之外的额外属性,TypeScript为了安全,不会自动把Object.keys的结果窄化为精确的键类型。
不用额外封装Object.keys的话,有几个直接可行的解决办法:
1. 直接在调用处做类型断言
这是最直接的方式,和你封装getKeys的逻辑本质一样,只是把断言写在调用Object.keys的地方:
const example = { hello: true } (Object.keys(example) as (keyof typeof example)[]).reduce((acq, key) => { const value = example[key] // 现在类型正确,会被推断为boolean return acq }, {})
2. 改用Object.entries更省心
如果你的场景需要同时拿到键和值,用Object.entries配合类型断言会更高效,还能避免手动通过键取值:
const example = { hello: true } (Object.entries(example) as [keyof typeof example, typeof example[keyof typeof example]][]).reduce((acq, [key, value]) => { // key的类型是"hello",value是boolean,完全符合预期 return acq }, {})
3. 内联泛型函数(不用单独声明)
要是不想重复写冗长的类型断言,可以用一个内联的泛型函数包裹Object.keys,效果和你的getKeys一致,但不用单独定义函数:
const example = { hello: true } (<T extends object>(obj: T) => Object.keys(obj) as (keyof T)[])(example).reduce((acq, key) => { const value = example[key] return acq }, {})
小补充:为什么TypeScript会有这个限制?
这里顺便解释下背后的原因:TypeScript的类型是结构化且开放的,比如你定义了一个{ hello: boolean }类型的对象,它在运行时可能还被添加了其他属性(比如用Object.assign),所以Object.keys返回所有键的string[]是更安全的默认行为。只有当你确定对象没有额外属性时,用类型断言窄化类型才是安全的。
内容的提问来源于stack exchange,提问作者ThomasReggi
相关产品推荐
相关产品推荐

