泛型扩展上的TypeScript奇怪类型行为 接口为空{ } 类型IfExtends=T扩展B?Y:N 让a:IfExtends///type从不 设b:keyof empty从不扩展?number:string///类型number

泛型扩展上的TypeScript奇怪类型行为 接口为空{ } 类型IfExtends=T扩展B?Y:N 让a:IfExtends///type从不 设b:keyof empty从不扩展?number:string///类型number,typescript,Typescript,在我看来,泛型类型IfExtends等于b的extends语句的类型。 但a的类型是never,b是number(扩展为true)。 为什么?这是将类型应用于从不的结果。如果将分配条件类型应用于联合,则结果将是将该条件类型应用于联合的每个组成部分的联合: interface empty{ } type IfExtends<T, B, Y, N> = T extends B ? Y : N let a: IfExtends<keyof empty, never, number,

在我看来,泛型类型
IfExtends
等于b的
extends
语句的类型。 但a的类型是never,b是number(扩展为true)。
为什么?

这是将类型应用于
从不
的结果。如果将分配条件类型应用于联合,则结果将是将该条件类型应用于联合的每个组成部分的联合:

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
never
是空的联合体(即没有组成成分的联合体)。将它加入任何其他联盟都会使它因此融化

因为它是一个空的联合体,当分布在它上面时,条件类型实际上永远不会得到计算,因为联合体中没有可以应用它的成分,我们只会得到
never
,而不管条件类型中的任何条件如何

使用实际的内联版本不会产生相同的结果,因为分布性只发生在裸类型参数上,
T
是裸类型参数,
keyof empty
不是

您可以通过将
T
封装在元组类型中来禁用分配性:

type X = never | number // just number, never is omitted
type IfExtends=[T]extends[B]?Y:N
设a:IfExtends///还设numberkeyof为空

我认为
b
类型解析正确。问题是,无论您作为
T
B
传递的类型组合是什么,如果
T
B
中的一个等于
never
,它总是返回
never
,这是
IfExtends
的结果。
type X = never | number // just number, never is omitted
type IfExtends<T, B, Y, N> = [T] extends [B] ? Y : N
let a: IfExtends<keyof empty, never, number, string> /// also numberkeyof empty