Создание фабрики с параметрами проверенного типа в Typescript 3.0

Мне очень нравятся новые извлекаемые списки параметров в TS 3.0, и, чтобы узнать, как это работает, я хотел создать Factory.

У меня это работает:

class MyClass{
    constructor(paramOne: string, paramTwo: number, paramThree?: boolean) {

    }
}

class Factory<T extends new (...args: any[]) => any>{

    constructor(private constr: T) { }

    create(...params: T extends new (...args: infer P) => infer R ? P : never): T extends new (...args: infer P) => infer R ? R : never{
        return new this.constr(...params);
    }
}

const myFactory = new Factory(MyClass);

const instance = myFactory.create("hello", 55);

Ссылка на игровую площадку

Это довольно круто, но определение функции create () немного длинное и содержит некоторое количество дублирования. Я попытался упростить это:

create: T extends new (...args: infer P) => infer R ? (...args: P) => R : never = (...params: P) => {
    return new this.constr(...params);
}

Ссылка на игровую площадку

Как вы можете видеть на детской площадке, здесь есть ошибки:

Тип '(... params: any) => any' не может быть назначен типу 'T extends new (... args: infer P) => infer R? (... args: P) => R: never '.

а также

Остаточный параметр должен иметь тип массива.

Есть ли способ сделать так, чтобы это более короткое и простое объявление работало?


person Roaders    schedule 02.08.2018    source источник


Ответы (1)


Присвоение значения условному типу, когда некоторые аргументы типа все еще неизвестны, обычно проблематично, поэтому я бы не пошел по этому пути.

Чтобы упростить подпись, я бы использовал предопределенный тип InstanceType и определил специальный тип для извлечения аргументов конструктора.

class MyClass{
    constructor(paramOne: string, paramTwo: number, paramThree?: boolean) {

    }
}

type ConstructorArguments<T> = T extends new (...args: infer P) => any ? P : never

class Factory<T extends new (...args: any[]) => any>{

    constructor(private constr: T) { }

    create(...params: ConstructorArguments<T> ): InstanceType<T>{
        return new this.constr(...params);
    }
}

const myFactory = new Factory(MyClass);

const instance = myFactory.create("hello", 55)
person Titian Cernicova-Dragomir    schedule 02.08.2018