Возвращает конструктор универсального типа в TypeScript - PullRequest
0 голосов
/ 02 декабря 2018

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

Пожалуйста, проверьте следующий пример:

Это часть абстрактного класса:

 getModel():  (new () => T) {
    throw new Error('Method not implemented.'); // Error because don't know how to fix it
}

Когда в производном классе я пытаюсь реализовать его следующим образом:

getModel(): typeof User {
    return User;
}

У меня следующая ошибка:

Type '() => typeof User' is not assignable to type '() => new () => User'.

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

Так что вопрос - как указать на абстрактном уровне класса, что метод возвращает конструктор универсального типа, и я могу пропустить реализацию этого метода у потомкауровень класса?Или, может быть, я неправильно указываю возвращаемую подпись на уровне абстрактного класса?

РЕДАКТИРОВАТЬ:

Пожалуйста, проверьте странную проблему.Классы A и B отличаются только наличием явного конструктора.И в RealA не работает, и RealB работает тот же метод getModel ().

class A {
a = '';
constructor(a: string) {

}
}

class B {
    a = '';
    static test(): void {
        console.log('I do work');
    }
}

abstract class Base<T> {
    Prop: T;
    constructor(TCreator: { new (): T; }) {
        this.Prop = new TCreator();
    }

    getModel(): (new () => T) {
        throw new Error('Method not implemented.'); // Error because don't know how to fix it
    }
}

class RealA extends Base<A> {
    getModel(): typeof A { // doesn't work - compilation error
        return A;
    }
}

class RealB extends Base<B> {
    getModel(): typeof B { // works
        return B;
    }
}

var test = new RealA(A); // compile error
var test2 = new RealB(B)

Для класса RealA та же ошибка

() => typeof A' is not assignable to type '() => new () => A'

1 Ответ

0 голосов
/ 02 декабря 2018

Ожидается ошибка, так как конструктор для класса A имеет обязательный аргумент.Абстрактный класс ограничивает передаваемый ему конструктор без аргументов (new () => T).

Простое решение состоит в том, чтобы удалить конструктор в A.

Если вы хотите иметь возможность передавать классы, которые имеют конструкторы, требующие аргументов, вам нужно будет изменить определениебазовый класс для захвата типа конструктора и получения constructor в качестве обязательных аргументов (с использованием кортежей в остальных параметрах )

class A {
    a = '';
    constructor(a: string) {

    }
}

class B {
    a = '';
    static test(): void {
        console.log('I do work');
    }
}

type ArgumentTypes<T> = T extends new (...a: infer A) => any? A : [] 
abstract class Base<T extends new (...a: any[])=> any> {
    Prop: InstanceType<T>;
    constructor(TCreator: T, ...a: ArgumentTypes<T>) {
        this.Prop = new TCreator(...a);
    }

    getModel(): T {
        throw new Error('Method not implemented.'); // Error because don't know how to fix it
    }
}

class RealA extends Base<typeof A> {
    getModel(): typeof A { // doesn't work - compilation error
        return A;
    }
}

class RealB extends Base<typeof B> {
    getModel(): typeof B { // works
        return B;
    }
}

var test = new RealA(A, ""); // ok
var test2 = new RealB(B)
...