首页 > 解决方案 > 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 是数字(扩展为真)。为什么?

标签: typescript

解决方案


这是将分布式条件类型应用于 的结果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 

游乐场链接


推荐阅读