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

Wad*_*ndy 5 generics typescript

我正在开发一个通用的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`
Run Code Online (Sandbox Code Playgroud)

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

如果我只依赖于我声明的类所给出的类型,那么构建函数的返回类型总是如此BaseClass,而且我必须创建泛型Factory<typeof Foo>而不是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`
Run Code Online (Sandbox Code Playgroud)

但是,如果我希望工厂类型接口正常工作,我必须维护一个镜像的并行类型定义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`
Run Code Online (Sandbox Code Playgroud)

必须有更好的方法将a转换typeof X为a X或反之亦然?

jca*_*alz 8

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


更新:

从TypeScript 2.8开始,有一个预定义的类型函数InstanceType<>,它调用类构造函数的类型并使用条件类型推断而不是查找来计算其实例的类型.所以,你可以从现在获得typeof XX使用InstanceType<typeof X>.但(typeof X)['prototype']下面仍然有效.


要获取typeof XX,你通常可以查找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())
  }
}
Run Code Online (Sandbox Code Playgroud)

然后以下工作:

let factory = new Factory(Foo)
let fooInstance = factory.build() // Foo, as desired.
Run Code Online (Sandbox Code Playgroud)

这有帮助吗?祝好运!