首页 > 解决方案 > 如何在方法中使用“this”创建类的新实例?

问题描述

我正在寻找一种this从类方法中调用 new 的方法。

class Example {
  fork() {
    return new this();
  }
}

const x = new Example().fork(); // instance of example

class Alpha extends Example {}

const x = new Alpha().fork(); // expected instance of Alpha but is example

标签: typescript

解决方案


我假设您的意思是您想要调用new this.constructor()(参见MDN 文档)而不是new this(),因为类的实例也将是类构造函数的情况非常罕见。在运行时,这就是您所需要的。


不幸的是constructor,TypeScript 中的 for 输入很乱。有关详细信息,请参阅microsoft/TypeScript#3841,但主要问题是,由于子类构造函数可能需要与其超类构造函数不同的一组参数,如果this.constructor是强类型,那么许多class层次结构将无法形成有效的子类型层次结构,因此会违反可替代性

因此在 TypeScript 中,constructor仅键入为Function,因此new this.constructor()会产生错误:

return new this.constructor(); // error!
// This expression is not constructable.

为了告诉编译器这this.constructor是一个零参数构造函数,您必须使用这样的类型断言:

class Example {
  fork(): this {
    return new (this.constructor as new () => this)()
  }
}

constructor或向您的类添加强类型属性声明,如下所示:

class Example2 {
  ['constructor']: new () => this
  fork(): this {
    return new this.constructor()
  }
}

两种解决方案都适用于您提供的示例用例:

const x = new Example().fork(); // Example
class Alpha extends Example { }    
const y = new Alpha().fork(); // Alpha

但是这两种解决方案都不会阻止您调用fork()其构造函数需要参数的子类的实例

class Blop extends Alpha {
  constructor(x: string) {
    super();
    console.log(x.toUpperCase());
  }
}
const z = new Blop("oops").fork(); // error at runtime!!

如果没有对 microsoft/TypeScript#3841 的良好解决方案,我认为这可能是你能得到的最好的解决方案。


Playground 代码链接


推荐阅读