Универсальная фабричная функция Typescript, включая параметры созданного объекта - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь создать фабричный класс в Typescript.Фабрика должна быть настроена для создания определенного класса объектов, включая параметры по умолчанию, установленные при инициализации фабрики.

Вот что я придумал до сих пор:

type Constructor<T> = new(...args: any) => T;

class Factory<T> {
    private params: ConstructorParameters<Constructor<T>>;
    private ctor: Constructor<T>;
    init<TCtor extends Constructor<T>>(tConstructor: TCtor,
        ...params: ConstructorParameters<TCtor>)
    {
        this.ctor = tConstructor;
        this.params = params;
    }

    create(): T {
        return new this.ctor(...this.params);
    }
}

class ClassWithParams { constructor(a: number) { } }

const factory = new Factory<ClassWithParams>();
//factory.init(ClassWithParams);
// Compilation error - missing param a

factory.init(ClassWithParams, 1);
console.log(factory.create());
// instance of ClassWithParams

Приведенный выше код работает хорошо ( Машинопись на игровой площадке ).Тем не менее, он требует init() вызова фабрики сразу после строительства.Я не могу переместить код init() в конструктор, потому что init() опирается на универсальный параметр TCtor для правильной проверки типов списка параметров.

Я мог бы сделать TCtor универсальным параметромвместо этого, но это будет означать, что каждый раз, когда на Factory дается общая ссылка, необязательно указывать дополнительный параметр типа.

Любые идеи по удалению этого вызова init()?

1 Ответ

1 голос
/ 24 июня 2019

Что не так со следующим кодом

type Constructor<T> = new (...args: any[]) => T;

class Factory<T, C extends Constructor<T> = Constructor<T>> {
    params: ConstructorParameters<C>;
    ctor: Constructor<T>;
    constructor(tConstructor: Constructor<T>,
        ...params: ConstructorParameters<C>) {
        this.ctor = tConstructor;
        this.params = params;
    }

    create(): T {
        return new (this.ctor)(...this.params)
    }
}
class ClassWithParams { constructor(a: number) { this.a = a; } a: number } 

const factory1 = new Factory(ClassWithParams);

const factory2 = new Factory(ClassWithParams, '1');

const factory3 = new Factory(ClassWithParams, 0);


const value = new Factory(ClassWithParams, 0).create().a;

Как видно на этой детской площадке , это удобно и правильно.

...