如何着手理解类型 `new (...args: any[]) => any`

How to go about understanding the type `new (...args: any[]) => any`

我正在通读 class-validator 库的代码,其中包含以下 isInstance 方法:

/**
 * Checks if the value is an instance of the specified object.
 */
isInstance(object: any, targetTypeConstructor: new (...args: any[]) => any) {
    return targetTypeConstructor
        && typeof targetTypeConstructor === "function"
        && object instanceof targetTypeConstructor;
}

关于如何理解类型 new (...args: any[]) => any 有什么想法吗?这是我第一次看到这种类型的构造...

new (...args: any[]) => any

此类型指定一个函数,该函数接受任意数量的 any 类型参数,returns any 值,并且可以用 new.

构造函数是一种特殊类型的函数,它在运行时强制使用 new 关键字进行调用,但在 TypeScript 中,可以静态检测到,因此 targetTypeConstructor 指定任意构造函数作为isInstance().

的第二个参数

为此,检查

似乎是多余的
typeof targetTypeConstructor === "function"

因为 targetTypeConstructor : new (...args: any[]) => any 在编译时由 TypeScript 强制执行。

如果传递的值是 null,它已经被 targetTypeConstructor && ... 条件无效,在运行时 是必需的,以防止 object instanceof targetTypeConstructortargetTypeConstructor 由于步骤 4 实际上是 null 的情况下抛出 TypeError§12.10.4 of the ECMAScript Specification:

12.10.4 Runtime Semantics: InstanceofOperator ( V, target )

  1. If Type(target) is not Object, throw a TypeError exception.
  2. Let instOfHandler be ? GetMethod(target, @@hasInstance).
  3. If instOfHandler is not undefined, then

    a. Return ToBoolean(? Call(instOfHandler, target, « V »)).

  4. If IsCallable(target) is false, throw a TypeError exception.
  5. Return ? OrdinaryHasInstance(target, V).

NOTE

Steps 4 and 5 provide compatibility with previous editions of ECMAScript that did not use a @@hasInstance method to define the instanceof operator semantics. If an object does not define or inherit @@hasInstance it uses the default instanceof semantics.

表示参数targetTypeConstructor是一个接受参数的函数,可以作为构造函数(可以使用withnew关键字创建实例).您可以传递一个简单的函数或一个不是 abstracts.

的 class

有关更多信息,您可以查看 Typescript Playground

中的示例

让我们将类型缩减为更小、更容易理解的小块,然后重新构建完整的内容。

首先,让我们把new从我们的脑海中删除并关注定义的后半部分:

(...args: any[]) => any

接下来让我们暂时忘记参数:

() => any

希望这是一个熟悉的函数,returns 键入 any

接下来我们可以在args中添加回来:

(...args: any[]) => any

...args: any[] 正在使用 Rest Parameters 结构,它本质上说可以有任意数量的所提供类型 any 的参数。因为有未知数量的 any 个参数,参数的类型是 any.

的数组

所以现在希望这是一个接受任意数量参数(any 类型)和 returns 类型 any.

的函数是有意义的

最后我们可以加回new关键字得到:

new (...args: any[]) => any

这里的new关键字指定这个函数可以被当作一个class构造函数,用new关键字调用。

这给了我们函数的全貌一个接受任意数量的参数(类型any)的函数returns类型any和可以用作带有 new 关键字的构造函数 .

在 API 的上下文中,它实际上允许您将任何 class 构造函数传递给函数。

分解成碎片:

new
TypeScript 中的这个关键字指定了给定 属性 的构造函数应该是什么样子。这里的解释很好:.

(...args: any[]) => any
此语法描述了一个函数类型(构造函数是一个函数)。

...
是 ES6 扩展运算符。它是将所有数组元素一一列出的简写形式。

any[]
意味着 args 是一个数组,它的元素可以是任何类型。

=> any
指定函数的 return 类型。在这种情况下,它允许构造函数 return 任何类型。