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

TypeScript重载函数switch case报错,如何规避额外类型检查?

TypeScript联合类型函数重载的类型收窄优化

先看你遇到的问题:

原代码如下:

interface First {
    a: number
}

interface Second {
    b: number
}

type GeneralInterface = First | Second;
type Kind = 'First' | 'Second';

function getValue(kind: 'First', object: First): number
function getValue(kind: 'Second', object: Second): number
function getValue(kind: Kind, object: GeneralInterface): number {
    switch (kind) {
        case "First": {
            return object.a
        }
        case "Second": {
            return object.b
        }
    }
}

运行时触发TS错误:

TS2339: Property 'a' does not exist on type 'GeneralInterface'.   Property 'a' does not exist on type 'Second'.

当前的解决办法是加额外的in检查,但这会让代码变啰嗦,复杂接口场景下工作量还大。既然你确定参数组合只有指定的两种,有几个更优雅的方案:


方案1:直接使用类型断言

既然明确参数组合合法,在实现里直接用类型断言告诉TypeScript当前分支的object类型:

interface First {
    a: number
}

interface Second {
    b: number
}

type GeneralInterface = First | Second;
type Kind = 'First' | 'Second';

function getValue(kind: 'First', object: First): number
function getValue(kind: 'Second', object: Second): number
function getValue(kind: Kind, object: GeneralInterface): number {
    switch (kind) {
        case "First": {
            return (object as First).a;
        }
        case "Second": {
            return (object as Second).b;
        }
    }
}

这种方式最简单,完全不需要额外检查,适合你确定参数合法的场景。


方案2:自定义类型守卫

如果想兼顾类型安全和可读性,可以写一个简单的类型守卫函数,把类型判断逻辑抽离出来:

interface First {
    a: number
}

interface Second {
    b: number
}

type GeneralInterface = First | Second;
type Kind = 'First' | 'Second';

function isFirst(kind: Kind, obj: GeneralInterface): obj is First {
    return kind === 'First';
}

function isSecond(kind: Kind, obj: GeneralInterface): obj is Second {
    return kind === 'Second';
}

function getValue(kind: 'First', object: First): number
function getValue(kind: 'Second', object: Second): number
function getValue(kind: Kind, object: GeneralInterface): number {
    if (isFirst(kind, object)) {
        return object.a;
    } else if (isSecond(kind, object)) {
        return object.b;
    }
    throw new Error(`Invalid argument: ${kind}`);
}

类型守卫会让TypeScript自动收窄类型,复杂场景下还能复用守卫逻辑,代码更整洁。


方案3:重构为区分联合类型参数

把kind和object合并成一个参数,让TypeScript自动关联类型,彻底避免手动类型判断:

interface First {
    kind: 'First',
    a: number
}

interface Second {
    kind: 'Second',
    b: number
}

type GeneralInterface = First | Second;

function getValue(obj: GeneralInterface): number {
    switch (obj.kind) {
        case "First": {
            return obj.a;
        }
        case "Second": {
            return obj.b;
        }
    }
}

这种方式是TypeScript推荐的区分联合类型写法,TypeScript能完美识别每个分支的类型,代码最简洁,连函数重载都不需要了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:33:21