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

Difference in TypeScript between types `InstanceType<typeof MyClass>` and `: MyClass`

我一直在尝试了解使用 InstanceType 分配类型与仅使用 Class 名称之间是否有任何区别。

特别是,鉴于 class:

MyClass {

  public static foo: string = 'abc'

  public makeFoo() {
    // awesome maker
  }

}

当我想使用class的实例时,好像没有什么区别:

// inside some other Class
private myClassInstance: InstanceType<typeof MyClass> 
...
this.myClassInstance = new MyClass()

// inside some other Class
private myClassInstance: MyClass 
...
this.myClassInstance = new MyClass()

至少在 VSCode 中,我在使用这两者时没有发现任何明显的区别。但是我想一定存在差异,如果 TS 已经实施 InstanceType<>.

有人知道有什么不同吗?

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

  • 类实际上是JavaScript中的函数(更确切地说是构造函数,但主要是函数)
  • 这些构造函数的return是某一种类型(构造函数的prototype和可选的一些实例字段)

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

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

  • MyClass:一种包含class字段和方法的接口
  • typeof MyClass(这里MyClass指的是运行时class):构造函数

因为你没有指定构造函数,它的类型是 new () => MyClass 并且你可以从中提取 MyClass 感谢 InstanceType.

举一个现实世界的例子,假设您正在尝试实现一个工厂(returns classes 实例的函数)。一种天真的实现如下所示:

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

class A { }

const res = factory(A); // typeof A: not what we expect

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

但是,此实现有效:

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

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