TypeScript奇怪的类型行为在通用中扩展

时间:2020-10-30 05:53:16

标签: 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等于b的extends语句的类型。 但是a的类型从不,b的类型是数字(扩展为true)。 为什么?

1 个答案:

答案 0 :(得分:2)

这是对never应用distributive conditional类型的结果。如果将分布式条件类型应用于联合,则结果将是将该条件类型应用于联合的每个组成部分的联合:

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 

Playground Link

相关问题