在以下情况下,我无法理解为什么Temp
类型是never
。我知道为什么它与(...args: any) => infer R
兼容,但是如何从中推断出类型never
?
// type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type Temp = ReturnType<never>;
答案 0 :(得分:5)
TL; DR Distributive conditional type和never
是空联合
长版:
首先让我们了解为什么ReturnType<never>
成为never
有点令人惊讶:
从PR开始,介绍了never
类型:
从不为每种类型的子类型,并且可以分配给每种类型。
所以这意味着如果我们问never extend AnyOtherType
这个问题?答案应该永远是。因此,让我们向编译器询问这个问题:
type R = never extends (...args: any) => any ? "Y" : "N"; // Evaluates to "Y"
因此,确实存在定义,并且never
是(...args: any) => any
的子类型。但是,为什么ReturnType<never>
解析为never
?如果推断失败,则默认值通常是unknown
而不是never
(ref)。让我们在ReturnType
之外尝试这种推断:
type T0 = never extends (...args: any) => infer R ? R : any; //unknown
所以这是我们产生令人惊讶的结果的地方,T0
确实是unknown
,而ReturnType<never>
是never
,甚至认为我们所做的只是内联{ ReturnType
中的{1}}。
原因是distributive conditional types。在裸类型参数上具有条件的类型是分布式的。这意味着,如果T0
是一个联合,则每个联合组成将通过条件类型独立运行,并且所有独立结果将被联合以获得最终结果。例如:
T
编译器如何评估上述类型:
type T1 = ReturnType<(()=> number) | (() => string)> // number | string
好的,这与ReturnType<(()=> number) | (() => string)>
-> ReturnType<()=> number> | ReturnType<() => string>
-> ((()=> number) extends (...args: any) => infer R) | ((()=> string) extends (...args: any) => infer R)
-> number | string
有什么关系。 never
实际上是一个空的联合(refernce),这是一个没有组成部分的联合。这意味着在通过分布式条件类型运行never
时,实际上从不评估条件类型,因为在尝试进行分发时,没有任何内容可以分发。
我们可以在never
上创建一个非分发版本,方法是不将ReturnType
裸露,并将其放在一个元组中,例如:
T