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

If语句无法缩小嵌套类型内的联合类型?Foo与Bar类型差异解析

问题解析:Foo与Bar类型的差异导致类型收窄行为不同

先看代码示例:

type Foo = { type: 'a' | 'b' }
type Bar = { type: 'a' } | { type: 'b' }

function test(x: { type: 'a' }) {}

function foo(x: Foo) {
  if (x.type === 'a') {
    test(x) // 错误
  }
}
function bar(x: Bar) {
  if (x.type === 'a') {
    test(x) // 正常
  }
}

核心差异:两种类型的本质不同

  • Foo是单个对象类型,它的type属性是联合类型'a' | 'b'。也就是说,所有Foo类型的对象,都拥有同一个type属性,只是属性值可以在'a'和'b'之间二选一。
  • Bar是对象类型的联合,它表示一个值要么是{ type: 'a' }类型,要么是{ type: 'b' }类型。这是两个完全独立的对象类型的组合。

类型收窄的行为差异

当用x.type === 'a'做判断时:

  • 对于Bar类型:TypeScript可以直接把x收窄到{ type: 'a' }这个分支——因为Bar的每个联合分支都是独立的对象,判断type值后就能确定整个对象的精确类型,所以传给test完全匹配。
  • 对于Foo类型:判断x.type === 'a'只能收窄x.type这个属性的类型为'a',但整个x依然是Foo类型。TypeScript无法保证x没有其他额外属性(比如Foo的实例可能还包含type以外的字段),而test要求的是严格的{ type: 'a' }类型,因此会判定类型不匹配。

简单总结:Foo是「一个对象,属性值二选一」,Bar是「二选一的两个对象」,TypeScript对这两种类型的类型收窄逻辑完全不同。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:54:55