Создайте универсальную фабрику в машинописном тексте

Я пишу небольшую модельную систему для моего текущего проекта. Я хотел бы, чтобы потребитель библиотеки мог предоставить свое собственное определение модели для 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, а не any.

Обновлено 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();

Я открыл задачу в трекере машинописи здесь: https://github.com/Microsoft/TypeScript/issues/5493

Обновлено 1 декабря (нерешено)

Это, согласно трекеру машинописи, невозможно. Функция «Полиморфный this» работает только для нестатических членов класса, которые исключают конструктор.


person Xealot    schedule 30.10.2015    source источник


Ответы (1)


Вам нужно будет использовать специальный тип this:

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

На момент написания этой статьи эта функция была доступна только в ночных сборках TypeScript (npm install typescript@next) и будет доступна в TypeScript 1.7. См. https://github.com/Microsoft/TypeScript/pull/4910, если хотите чтобы отследить конкретную фиксацию или узнать больше о том, как работает this

person Ryan Cavanaugh    schedule 30.10.2015
comment
Отлично, теперь я знаю название того, что мне нужно! Я попробую это с TS@next, спасибо за совет. - person Xealot; 31.10.2015