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

TypeScript中extends类型关系疑问:联合类型的矛盾判定

问题根源:TypeScript的分布式条件类型

你遇到的所有“矛盾”,本质都是TypeScript的分布式条件类型在起作用——这是TypeScript处理联合类型时的特殊逻辑,很多人会忽略这个细节。

简单来说:当条件类型中extends左边的检查类型是一个裸类型参数(没有被包裹在元组、对象等结构里)时,TypeScript会自动把联合类型拆成单个成员,分别代入条件判断,最后把所有分支的结果合并成新的联合类型。

第一个例子:doesExtend<'a' | 'b', 'a'>('yes')合法的原因

看函数定义:

function doesExtend<A, B>(_: (A extends B ? 'yes' : 'no')) { }

当你传入A = 'a' | 'b'、B = 'a'时:

  • 因为A是裸类型参数且为联合类型,触发分布式逻辑
  • TypeScript会把联合拆成两个独立判断:
    1. 'a' extends 'a' → 结果为'yes'
    2. 'b' extends 'a' → 结果为'no'
  • 最终参数的类型变成'yes' | 'no',所以传入'yes'完全符合类型要求(它是联合类型的成员之一)

第二个例子:WhoExtendsWho<'a' | 'b', 'a'>返回矛盾联合的原因

同样是分布式条件类型在生效:

type WhoExtendsWho<A, B> = A extends B
    ? B extends A
        ? 'A extends B, and B extends A'
        : 'A extends B, but B does not extend A'
    : B extends A
        ? 'A does not extend B, but B extends A'
        : 'A does not extend B, and B does not extend A';

当A = 'a' | 'b',B = 'a'时:

  1. 把联合成员'a'代入判断:
    • 'a' extends 'a' → 进入第一个分支
    • 接着判断'a' extends 'a' → 为true,得到结果'A extends B, and B extends A'
  2. 把联合成员'b'代入判断:
    • 'b' extends 'a' → 进入第三个分支
    • 接着判断'a' extends 'b' → 为false,得到结果'A does not extend B, and B does not extend A'
  3. 最后把两个分支的结果合并,就得到了你看到的矛盾联合类型

如何避免分布式行为?

如果你想让联合类型作为整体进行判断,而不是拆分单个成员,可以把检查类型用元组包裹,破坏“裸类型参数”的条件:

修改后的函数:

function doesExtend<A, B>(_: ([A] extends [B] ? 'yes' : 'no')) { }
doesExtend<'a' | 'b', 'a'>('yes'); // 现在会报错,符合预期

修改后的类型工具:

type WhoExtendsWho<A, B> = [A] extends [B]
    ? [B] extends [A]
        ? 'A extends B, and B extends A'
        : 'A extends B, but B does not extend A'
    : [B] extends [A]
        ? 'A does not extend B, but B extends A'
        : 'A does not extend B, and B does not extend A';

type X = WhoExtendsWho<'a' | 'b', 'a'>; // 返回"A does not extend B, but B extends A",符合预期

内容的提问来源于stack exchange,提问作者Trident D'Gao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:31:19