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

TypeScript中两种联合类型实现方式的差异是什么?

TypeScript类型X与Y的区别分析

类型定义示例

// 类型X:单一对象类型,属性a为联合值
type X = {
    a: "hi" | "bye";
    b: number;
}

// 类型Y:两个对象类型的联合
type Y = { a: "hi", b: number } | { a: "bye", b: number }

实现方式回顾

类型X的生成方式

通过MergeUnion工具类型将联合类型合并为单一对象:

type A = { a: "hi", b: number }
type B = { a: "bye", b: number }
type C = A | B

type MergeUnion<T> = { [K in ({} & keyof T)]: T[K] };

type X = MergeUnion<C>

类型Y的生成方式

直接取两个对象类型的联合(注:原代码中a|b应为笔误,实际是A|B):

type Y = A | B;

核心差异点

1. 类型本质不同

  • X是单一对象类型:代表一个同时拥有a和b属性的统一结构,a的取值范围是"hi"或"bye",b必须是number类型,没有分支区分。
  • Y是对象类型的联合:代表两种独立的对象结构之一——要么是{a: "hi", b: number},要么是{a: "bye", b: number},类型本身是两个结构的集合。

2. 类型检查与窄化行为不同

  • 使用X类型时,TypeScript不会对a的具体值做额外窄化,可自由修改a在联合范围内的值:
    const x: X = { a: "hi", b: 1 };
    x.a = "bye"; // 完全合法,符合X的类型定义
    
  • 使用Y类型时,TypeScript会根据初始赋值自动窄化类型,后续修改超出窄化范围会触发错误:
    const y: Y = { a: "hi", b: 1 };
    // 此时y被窄化为{ a: "hi", b: number }类型
    y.a = "bye"; // 类型错误:不能将类型"bye"分配给类型"hi"
    
    若要修改,需通过类型断言绕过窄化:
    (y as Y).a = "bye"; // 合法
    

3. 类型操作的表现差异

当对两种类型进行工具类型操作时,结果可能不同:

  • 本示例中X['a']和Y['a']都会得到"hi" | "bye",表现一致;但如果涉及可选属性、索引签名或条件类型时,差异会更明显。比如若其中一个子类型添加额外属性,合并后的X会包含该属性的联合类型,而Y会保留分支结构。

兼容性

在当前示例的结构下,X和Y是双向兼容的:

  • X类型的对象可以赋值给Y类型,因为X的每个可能值都符合Y的其中一个分支。
  • Y类型的对象也可以赋值给X类型,因为Y的每个分支都完全匹配X的结构要求。
    但这种兼容性仅针对当前结构,若类型结构发生变化(比如某分支添加可选属性),兼容性可能被打破。

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:20:06