点
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
? Return
: never;
是获取任何函数的返回类型,而不是根据其参数类型拒绝调用签名.您输入为Type
的任何呼叫签名都应该可分配给(...args: never[]) => infer Return
.That is, 103 is meant to be a supertype of all call signatures; it should be a 100 for functions.有关此的更多讨论,请参阅Alternative for "any function" ((...args: any[]) => any) without using any.
现在,由于您实际上扔掉了Type
的参数,而您实际上不是calling类型Type
的函数,因此有多种方法可以在TypScript中编写函数顶级类型,以实现此目的. 以下是我认为的偏好降序排列的列表:
(...args: never) => infer Return
(...args: any) => infer Return
(...args: any[]) => infer Return
(...args: never[]) => infer Return
函数类型的参数类型为contravariant(请参阅Unions15/2887218">Difference between Variance, Covariance, Contravariance, Bivariance and Invariance in TypeScript).这意味着如果您希望您的函数类型匹配更多函数类型,则该类型的参数必须匹配更少的参数类型. 每string
就是string | number
,这意味着每(x: string | number)=>void
就是(x: string)=>void
,反之亦然. Unions个函数最终看起来像接受了intersections个参数(参见the TS3.3 release notes for calling unions of functions).如果您正在寻找函数的顶级类型(概念上是所有函数类型的联合),则参数需要为bottom type(概念上是所有参数类型的交集).
那么,所有可能的参数列表的交集是什么? 什么类型可以分配给每一个可能的tuple个,例如[a: string]
、[]
和[a: number, b: string]
等? 嗯,the never type可分配给所有类型.它是TypScript的底部类型. 这意味着从类型安全的Angular 来看,(...args: never) => infer Return
是最正确的功能顶级类型.
您也可以为此使用the any
type,例如(...args: any) => infer Return
. any
类型是故意不安全的,并且表现得像顶部类型和底部类型.如果您确实不关心某个类型而只是想防止错误,则可以使用any
. 因此,如果你只是推断Return
,(...args: any) => infer Return
也是完全可以接受的.
您还可以使用(...args: any[]) => infer Return
,因为any[]
将匹配任何可能的数组类型.
然后是(...args: never[]) => infer Return
.类型never[]
意味着"您无法索引到的数组".它是几乎所有数组类型的子类型,但并不完全是所有数组类型的intersection.它仍然匹配几乎所有函数,但当您try call它时,它的行为应该有所不同.类型(...args: never) => ?
的函数应该完全不可调用,而类型(...args: never[]) => ?
的函数应该可以用零参数调用.实际上,TypScript将这些类型视为本质上相同的,这在技术上是不正确的,但在实践中不会造成太大问题.查看microsoft/TypeScript#48840以了解围绕这些类型的有趣错误和奇怪之处.
但是,我们在这里根本没有调用该函数,所以这主要是学术性的.就GetReturnType
而言,never[]
和never
一样好.