TypeScript 嵌套联合类型经Object.entries处理后丢失非共享键问题
问题原因说明
原生Object.entries的类型定义默认返回值为[string, T][],其中T是目标对象所有属性值的联合类型。在你提供的嵌套场景下,两层遍历之后TypeScript的类型推断只能识别到subval的公共属性a,无法自动保留subval完整的联合类型结构,导致in操作符的类型收窄逻辑失效。
这个表现不属于TypeScript的已知Bug,是类型系统设计阶段为了兼顾通用性做的权衡:原生类型定义不会针对嵌套遍历这种小众场景做特殊处理,避免过度收紧类型导致通用场景下的使用报错。
可行的解决方法
- 方法一:显式标注联合类型
提前定义第二层值的完整联合类型,遍历的时候给subval做显式标注,即可让in收窄正常生效:
type SubVal = { a: string } | { a: string, b: number } (params: Params) => { Object.entries(params).map(([headkey, sub])=>{ Object.entries(sub).map(([subkey, subval: SubVal])=>{ subval.a if('b' in subval) subval.b // 无报错 }) }) }
- 方法二:自定义精确类型的
entries工具
封装自定义的entries方法,绑定更精确的类型定义,保留对象键值的对应类型关系:
type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][] function entries<T extends object>(obj: T): Entries<T> { return Object.entries(obj) as unknown as Entries<T> } (params: Params) => { entries(params).map(([headkey, sub])=>{ entries(sub).map(([subkey, subval])=>{ subval.a if('b' in subval) subval.b // 无报错 }) }) }
- 方法三:临时类型断言
如果只是临时处理少量场景,可以直接通过类型断言跳过推断限制:
if('b' in (subval as { a: string, b?: number })) (subval as { a: string, b: number }).b
内容的提问来源于stack exchange,提问作者BobtheMagicMoose
相关产品推荐
相关产品推荐

