为何TypeScript的Extract工具类型提取子集而非返回完整联合类型?
TypeScript Extract工具类型与直接条件类型的差异解析
先看你给出的代码示例:
Extract工具类型的使用:
type x = 'abc' | 'def' | 32; type x2 = Extract<x, number>; // ^? type x2: 32
Extract的官方定义是:
type Extract<T, U> = T extends U ? T : never;
但你直接写下面的代码时,结果却是never:
type x2 = x extends number ? x : never; // ^? type x2: never
核心原因:分布式条件类型的触发规则
TypeScript里的条件类型有个特殊行为:当条件类型的左侧操作数是联合类型,且这个联合类型处于泛型参数的位置时,会触发分布式条件类型——也就是把联合类型的每个成员单独拆分出来,分别执行条件判断,最后将所有结果合并成新的联合类型。
Extract之所以能得到正确结果,就是因为它是泛型定义:
- 把联合类型
x拆分成'abc'、'def'、32三个成员 - 依次判断每个成员是否
extends number:'abc' extends number→ 不成立,返回never'def' extends number→ 不成立,返回never32 extends number→ 成立,返回32
- 最终合并结果为
never | never | 32,也就是32
而你直接写x extends number ? x : never时,x是作为一个整体的联合类型来判断的——整个'abc' | 'def' | 32是否能赋值给number?显然不行,因为里面包含字符串类型,所以条件不成立,直接返回never。
如果要模拟Extract的效果,只要把逻辑封装成泛型类型,让联合类型处于泛型参数位置即可:
type MyExtract<T, U> = T extends U ? T : never; type x2 = MyExtract<x, number>; // 结果同样是32
内容的提问来源于stack exchange,提问作者coure2011
相关产品推荐
相关产品推荐

