You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:54:00