TypeScript 类型 `InstanceType<typeof MyClass>` 和 `: MyClass` 之间的差异

don*_*don 18 constructor instance typescript typescript-typings

InstanceType我一直试图了解使用分配类型或简单地使用类名称之间是否有任何区别。

特别是,考虑到该类:

MyClass {

  public static foo: string = 'abc'

  public makeFoo() {
    // awesome maker
  }

}
Run Code Online (Sandbox Code Playgroud)

当我想使用类的实例时,似乎没有区别:

// inside some other Class
private myClassInstance: InstanceType<typeof MyClass> 
...
this.myClassInstance = new MyClass()
Run Code Online (Sandbox Code Playgroud)

和

// inside some other Class
private myClassInstance: MyClass 
...
this.myClassInstance = new MyClass()
Run Code Online (Sandbox Code Playgroud)

至少在 VSCode 中,使用两者中的任何一个都没有任何明显的差异。不过我想如果 TS 实现了InstanceType<>.

有人知道有什么区别吗?

Twi*_*her 22

辅助InstanceType类型的存在是因为实际上有两件事:

  • 类实际上是 JavaScript 中的函数(更准确地说是构造函数,但主要是函数)
  • 这些构造函数的返回是一种特定类型(prototype构造函数的返回值和可选的一些实例字段)

在 TypeScript 中,当您声明 a 时class,您实际上声明了两件事:构造函数的类型和生成的实例(类字段和方法)的类型。

在您的示例中,当您编写时,class MyClass您实际上创建了一个 JavaScript 类和两种 TypeScript 类型:

  • MyClass:一种包含类字段和方法的接口
  • typeof MyClass(本例MyClass中指的是运行时类):构造函数

由于您没有指定构造函数,因此它的类型是new () => MyClass,您可以MyClass通过InstanceType.

作为一个现实世界的示例,假设您正在尝试实现一个工厂(返回类实例的函数)。一种简单的实现如下所示:

declare function factory<T>(ctor: T): T;

class A { }

const res = factory(A); // typeof A: not what we expect
Run Code Online (Sandbox Code Playgroud)

这是行不通的,因为我们实际上返回了构造函数本身的类型。

然而,这个实现是有效的:

type Constructor = new (...args: any[]) => any;

declare function factory<T extends Constructor>(ctor: T): InstanceType<T>;

class A { }

const res = factory(A); // A: what we expect
Run Code Online (Sandbox Code Playgroud)

因为InstanceType帮助我们声明了返回值类型是构造函数的返回值类型。