typescript - TypeScript 在泛型中扩展的奇怪类型行为
问题描述
interface empty{
}
type IfExtends<T, B, Y, N> = T extends B ? Y : N
let a: IfExtends<keyof empty, never, number, string> /// type never
let b: keyof empty extends never?number:string /// type number
在我看来,泛型类型IfExtends
等于 bextends
语句的类型。但是 a 的类型从不,b 是数字(扩展为真)。为什么?
解决方案
这是将分布式条件类型应用于 的结果never
。如果将分布式条件类型应用于联合,则结果将是将该条件类型应用于联合的每个组成部分的联合:
type IfExtends<T> = T extends number ? "Y" : "N"
type A = IfExtends<number | string> // = IfExtends<number> | IfExtends<string> = "Y" | "N"
那么这有什么关系never
呢?never
如果我们尝试与任何其他类型联合,我们可以获得提示:
type X = never | number // just number, never is omitted
never
是空联合,即没有成分的联合。将其添加到任何其他工会都会因此而消失。
因为它是空联合,所以在对其进行分配时,条件类型实际上永远不会被评估,因为联合中没有要应用它的成分,我们只是never
不管条件类型中的任何条件都得到
使用实际的内联版本不会产生相同的结果,因为分配性只发生在裸类型参数上,T
是裸类型参数,keyof empty
不是。
您可以通过封装T
在元组类型中来禁用分布:
type IfExtends<T, B, Y, N> = [T] extends [B] ? Y : N
let a: IfExtends<keyof empty, never, number, string> /// also numberkeyof empty