打字稿将`typeof Foo`转换为`Foo`

时间:2017-12-29 20:49:08

标签: typescript generics

我正在开发一个通用的Typescript接口,其中工厂类使用特定的类进行实例化,并且具有负责创建该类的各种实例的方法。我理想的类型界面,我似乎无法实现,如下:

class BaseModel { /* impl */ }
class Foo extends BaseModel { /* impl */ }
class Factory<T extends BaseModel> { /* impl */ }

let factory : Factory<Foo> = new Factory(Foo)
let fooInstance = factory.build() // returns type: `Foo`

但是我无法弄清楚如何在不损害返回类型或维护并行构造函数类型定义的情况下获得Factory<T>的声明来实现此目的。

如果我只依赖于我声明的类所给出的类型,那么构建函数的返回类型总是BaseClass,而且我必须使用通用Factory<typeof Foo>而不是{ {1}}:

Factory<Foo>

但是,如果我希望工厂类型接口正常工作,我必须维护一个镜像class BaseModel { static classMethod() : string { return 'i am class method' } hello() { return 'hello world' } } class Foo extends BaseModel {} class Factory<T extends typeof BaseModel> { private _modelClass : T constructor(modelClass : T) { this._modelClass = modelClass } build() { return new this._modelClass() } echoClassMethod() { console.log(this._modelClass.classMethod()) } } let factory : Factory<typeof Foo> = new Factory(Foo) let fooInstance = factory.build() // Returns type `BaseClass` instead of `Foo` 的并行类型定义,但作为构造函数:

typeof BaseModel

必须有更好的方法将class BaseModel { static classMethod() : string { return 'i am class method' } hello() { return 'hello world' } } class Foo extends BaseModel {} // Have to maintain a separate type that // mirrors the class interface of my target class type BaseModelConstructor<T extends BaseModel> = { new(...args: any[]) : T classMethod() : string } class Factory<T extends BaseModel> { private _modelClass : BaseModelConstructor<T> constructor(modelClass : BaseModelConstructor<T>) { this._modelClass = modelClass } build() { return new this._modelClass() } echoClassMethod() { console.log(this._modelClass.classMethod()) } } let factory : Factory<Foo> = new Factory(Foo) let fooInstance = factory.build() // Correctly returns type `Foo` 转换为typeof X,反之亦然?

1 个答案:

答案 0 :(得分:8)

假设X是构造函数值的名称和名称 实例类型(当您声明class X {...}时会发生这种情况):

更新:

从TypeScript 2.8开始,有一个名为InstanceType<>的{​​{3}},它采用类构造函数的类型,并使用predefined type function而不是查找来计算其实例的类型。因此,您现在可以使用typeof XXInstanceType<typeof X>。但是下面的(typeof X)['prototype']仍有效。

要从typeof X转到X,您通常可以conditional type inference prototype构造函数类型的typeof X属性。例如,在下面我已将build()的返回类型注释为T['prototype']

class Factory<T extends typeof BaseModel> {
  private _modelClass : T

  constructor(modelClass : T) {
    this._modelClass = modelClass
  }

  // note the declared return type
  build(): T['prototype'] {
    return new this._modelClass()
  }

  echoClassMethod() {
    console.log(this._modelClass.classMethod())
  }
}

然后以下工作:

let factory = new Factory(Foo)
let fooInstance = factory.build() // Foo, as desired.

这有帮助吗?祝你好运!