在打字稿中创建一个通用工厂

Xea*_*lot 5 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道如何完成这里的模式。只是让工厂吐出正确的实例很容易,但是像clone/ refreshon 之类的东西BaseModel也需要返回Model,而不是any.

更新 10/2

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

// 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();
Run Code Online (Sandbox Code Playgroud)

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

12/1 更新(未解决)

根据打字稿问题跟踪器,这是不可能的。“多态this”功能仅适用于排除构造函数的非静态类成员。

Rya*_*ugh 2

您需要使用特殊this类型:

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

在撰写本文时,此功能仅在 TypeScript ( npm install typescript@next) 的夜间版本中可用,并将在 TypeScript 1.7 中提供。如果您想跟踪特定提交或了解有关工作原理的更多信息,请参阅https://github.com/Microsoft/TypeScript/pull/4910this