Inferring Within Conditional Types部分中,他们提供了一个例子:

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
  ? Return
  : never;

type Num = GetReturnType<() => number>;
type Str = GetReturnType<(x: string) => string>;
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>;

但为什么他们在这里使用never[]呢?

推荐答案

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一样好.

Typescript相关问答推荐

如果一个变量不是never类型,我如何创建编译器错误?

如何将类型从变量参数转换为返回中的不同形状?

TypeScrip表示该类型不可赋值

寻址对象中路径的泛型类型

如何将父属性类型判断传播到子属性

ANGLE订阅要么不更新价值,要么不识别价值变化

我怎样才能正确地输入这个函数,使它在没有提供正确的参数时出错

我可以使用typeof来强制执行某些字符串吗

tailwind css未被应用-react

使用Type脚本更新对象属性

如何在打字角react 式中补齐表格组

在Google授权后由客户端接收令牌

Rxjs将省略的可观测对象合并到一个数组中

如何将对象的字符串文字属性用作同一对象中的键类型

参数未映射泛型返回类型

TypeScript:方法获胜';t接受较窄类型作为参数

什么';是并类型A|B的点,其中B是A的子类?

如何避免TS2322;类型any不可分配给类型never;使用索引访问时

如何为对象创建类型,其中键是只读且动态的,但值是固定类型?

创建通过删除参数来转换函数的对象文字的类型