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

TypeScript在条件块中为何无法正确推断泛型类型的属性?

问题原因

TypeScript 目前不支持通过判断泛型参数的取值,自动收窄对应的条件类型结果。你虽然已经确认type的值为DataType.Bar,但 TS 不会联动把泛型T收窄为DataType.Bar,因此对应的Data<T>也不会自动收窄为BarData,依旧是联合类型FooData | BarData,所以无法直接访问BarData独有的属性。

解决方案

下面提供三种常用的修正方案,可根据项目场景选择:

1. 类型断言(最简单快速)

已经确认运行时逻辑正确的前提下,直接给data做类型断言即可:

if (type === DataType.Bar) {
    const barData = data as BarData;
    console.log(barData.otherKey)
    // getter调用也可以对key做断言解决报错
    console.log(getter('otherKey' as keyof Data<T>))
}

2. 自定义类型守卫(更安全)

封装类型守卫函数,同时关联type和data的类型判断,收窄逻辑更严谨:

// 新增类型守卫
function isBarData<T extends DataType>(type: T, data: Data<T>): data is BarData {
    return type === DataType.Bar
}

function func<T extends DataType>(type: T, data: Data<T>): void {
    const getter = <K extends keyof Data<T>>(key: K): Data<T>[K] => data[key]

    if (isBarData(type, data)) {
        // 这里data已经被自动收窄为BarData
        console.log(data.otherKey)
        console.log(getter('otherKey' as keyof Data<T>))
    }
}

3. 函数重载(最丝滑,无需额外断言)

如果可以调整函数定义,改用重载写法,TS 对固定参数组合的收窄支持更好:

enum DataType { Foo, Bar }
interface FooData { someKey: string }
interface BarData extends FooData { otherKey: string }

// 重载签名
function func(type: DataType.Foo, data: FooData): void
function func(type: DataType.Bar, data: BarData): void
// 实现签名
function func(type: DataType, data: FooData | BarData): void {
    const getter = <K extends keyof typeof data>(key: K) => data[key]

    if (type === DataType.Bar) {
        console.log(data.otherKey) // 无报错,自动推导为BarData
        console.log(getter('otherKey')) // 无报错
    }
}

内容的提问来源于stack exchange,提问作者DustInComp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:36:08