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

TypeScript中Extract<T, U>与手动条件判别类型行为不一致的问题

TypeScript中Extract<T, U>与手动条件判别类型行为不一致的问题

嘿,我来帮你拆解这个看起来有点反直觉的问题~你遇到的差异其实是TypeScript条件类型里的分布式特性在起作用,咱们一步步理清楚:

首先先把你的代码贴出来方便分析:

type PQR = 'p'|'q'|'r'; 
type P = 'p'; // 这个类型确实是 'p'
type JustP = Extract<PQR, P>; // 你说这里得到了 never?正常情况应该返回 'p' 才对哦
type NeverP = PQR extends P ? PQR : never; // 这个得到 never 是符合预期的

先搞懂Extract的本质:TypeScript内置的Extract<T, U>其实是这样实现的:

type Extract<T, U> = T extends U ? T : never;

看起来和你手动写的条件类型一模一样,但为什么结果会有差异?核心区别在于是否触发分布式条件类型:

  • 分布式特性只有当条件类型中的T是一个「裸类型参数」(也就是没有被数组、对象、元组等包裹的类型参数)时才会生效。当你给Extract传入联合类型PQR作为T时,TypeScript会自动把联合类型拆分成单个成员('p'、'q'、'r'),分别判断每个成员是否extendsP,最后把符合条件的成员重新组合成联合类型——正常来说这里就会返回'p'。

  • 而你手动写的PQR extends P ? PQR : never里,PQR是一个具体的联合类型,不是类型参数,所以不会触发分布式特性。TypeScript会把整个联合类型作为一个整体去判断:'p'|'q'|'r'是否完全extends'p'?显然不是,因为'q'和'r'都不满足,所以整个条件返回never。

如果想让手动写的条件类型和Extract表现一致,只要把它改成用类型参数的形式就行:

type MyExtract<T, U> = T extends U ? T : never;
type JustP2 = MyExtract<PQR, P>; // 这里就会正确返回 'p'

另外你提到Extract<PQR, P>得到了never,这有点反常,大概率是代码里的P定义和你想的不一样?比如是不是不小心写成了大写的'P',或者P是一个更宽泛的不兼容类型?可以再检查一下P的定义哦~

备注:内容来源于stack exchange,提问作者gbromios

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:39:26