在typescript中创建一个通用工厂

时间:2015-10-30 19:45:42

标签: typescript typescript1.6 typescript1.7

我正在为我当前的项目编写一个小模型系统。我希望库的使用者能够为API提供他们自己的模型定义。在查询服务器时,API应输出用户模型的实例。

// Library Code
interface InstanceConstructor<T extends BaseModel> {
    new(): T;
}

class Factory<T extends BaseModel> {
    constructor(private cls: InstanceConstructor<T>) {}

    get() {
        return new this.cls();
    }
}

class BaseModel {
    refresh() {
        // Refresh returns a new instance, but it should be of 
        // type Model, not BaseModel.
    }
}

// User Code
class Model extends BaseModel {
    // Custom Model
    do() {
        return true;
    }
}

我无法弄清楚如何在这里完成模式。只是让工厂吐出正确的实例非常简单,但是clone上的refresh / BaseModel之类的内容也需要返回Model,而不是{{1} }}

更新了10/2

在尝试了typescript @ next(此时技术上是1.8-dev)后,我似乎能够解决模型可以引用自身的问题(any),类型系统可以遵循它。但是,我无法

this

我在打字稿跟踪器上打开了一个问题: https://github.com/Microsoft/TypeScript/issues/5493

更新了12/1(未解决)

根据打字稿问题跟踪器,这是不可能的。 &#34;多态// Library Code export interface InstanceConstructor<T extends BaseModel> { new(fac: Factory<T>): T; } export class Factory<T extends BaseModel> { constructor(private cls: InstanceConstructor<T>) {} get() { return new this.cls(this); } } export class BaseModel { constructor(private fac: Factory<this>) {} refresh() { // get returns a new instance, but it should be of // type Model, not BaseModel. return this.fac.get(); } } // User Code, Custom Model export class Model extends BaseModel { do() { return true; } } // Kinda sucks that Factory cannot infer the "Model" type let f = new Factory<Model>(Model); let a = f.get(); let b = a.refresh(); &#34; feature仅适用于排除构造函数的非静态类成员。

1 个答案:

答案 0 :(得分:3)

You'll need to use the special this type:

class BaseModel {
    refresh(): this {
        // Refresh returns a new instance, but it should be of 
        // type Model, not BaseModel.
    }
}

At time of writing, this feature is only available in nightly builds of TypeScript (npm install typescript@next), and will be available in TypeScript 1.7. See https://github.com/Microsoft/TypeScript/pull/4910 if you want to track the specific commit or read more about how this works