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
相关产品推荐
相关产品推荐

