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

TypeScript泛型extends与直接extends语句的类型行为差异疑问

为什么泛型IfExtends和直接条件判断的结果不一样?

这事儿的核心原因是TypeScript的分布式条件类型在起作用,咱们一步步拆解来看:

首先先明确几个基础:

  • interface empty { } 的keyof empty类型就是never,因为空接口没有任何属性键。
  • 泛型里的T extends B和直接写的条件判断X extends Y ? A : B,在处理联合类型(包括never这种空联合)时逻辑完全不同。

1. 变量a的情况:泛型IfExtends触发了分布式条件类型

当你在泛型条件类型中使用T extends B时,如果T是一个联合类型(哪怕是空联合never),TypeScript会自动触发「分布式条件类型」的逻辑:把联合类型的每个成员单独拿出来,分别和B进行extends判断,最后把所有结果再合并成一个联合类型。

而never是一个空的联合类型——它没有任何成员可以拆分出来进行判断,所以整个条件类型的结果就直接是never,这就是为什么a的类型是never。

2. 变量b的情况:直接条件判断是非分布式的

而keyof empty extends never ? number : string这种写法,属于非分布式的条件类型:这里的extends是直接对整个类型(也就是never)进行判断,没有拆分联合类型的逻辑。

在TypeScript的类型系统里,never extends never是成立的(因为never是所有类型的子类型,包括它自己),所以这个条件判断会返回number,也就是b的类型是number。

举个更直观的例子验证

咱们换个非空的联合类型试试,你就能更清楚分布式和非分布式的区别:

type IfExtends<T, B, Y, N> = T extends B ? Y : N;

// 分布式:把'a'和'b'分别判断,结果是number | string
type Test1 = IfExtends<'a' | 'b', 'a', number, string>;

// 非分布式:整个联合类型'a'|'b'不extends 'a',结果是string
type Test2 = 'a' | 'b' extends 'a' ? number : string;

这样对比下来,你就能明白为什么同样是extends判断,泛型版本和直接写法会有不同结果啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:22:52