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

TypeScript:展开联合类型对象后如何实现类型区分?

问题:展开联合类型对象后如何维持类型区分

先定义如下联合类型:

type ExampleType = {
    type: "number",
    data: 0
} | {
    type: "string",
    data: "",
}

使用展开操作符解构后,type 与剩余的 data 变量失去了类型关联,无法通过type的判断收窄data的类型:

const example = (param: ExampleType) => {
    const {type, ...data} = param;

    if (type === 'number') {
        const result = data; // result仍为联合类型,未正确收窄
    }
}

但直接访问原对象属性时,类型收窄正常工作:

const example = (param: ExampleType) => {
    if (param.type === "number") {
        const result1 = param.data; // result1类型为0,符合预期
    }
}

请问能否通过展开操作符实现联合类型的区分?如果可以,具体怎么做?


解决方案

可以实现,核心是让TypeScript重新建立type和剩余data的类型关联,以下是两种可行方案:

方案一:自定义工具类型 + 类型断言

先定义工具类型,根据type字段提取对应联合成员的剩余属性类型:

type ExtractByType<T, Type extends T["type"]> = T extends { type: Type } ? Omit<T, "type"> : never;

之后在判断type后,对data做类型断言:

const example = (param: ExampleType) => {
    const {type, ...data} = param;

    if (type === 'number') {
        const result = data as ExtractByType<ExampleType, "number">;
        // result 类型为 { data: 0 },符合预期
    }

    if (type === 'string') {
        const result = data as ExtractByType<ExampleType, "string">;
        // result 类型为 { data: "" },符合预期
    }
}

方案二:重构原结构对象

把解构出的type和data重新组合成原联合类型的对象,让TypeScript自动完成类型收窄:

const example = (param: ExampleType) => {
    const {type, ...data} = param;
    const restructured = { type, ...data } as ExampleType;

    if (restructured.type === 'number') {
        const result = restructured.data; // 类型为0,符合预期
    }
}

原理说明

TypeScript解构剩余属性时,会将联合类型的剩余部分合并为无关联的联合,丢失了原联合成员中type与其他属性的绑定关系。因此需要手动通过工具类型或重构对象的方式,重新建立这种关联,才能实现类型收窄。


内容的提问来源于stack exchange,提问作者Денис Кирин

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 21:03:11