универсальный тип конструктора дочернего класса - PullRequest
0 голосов
/ 16 сентября 2018

Я ищу способ выразить тип [B, C] из следующего кода в общем виде.Если я наведите types, как это происходит в настоящее время, я получу const types: (typeof B | typeof C)[], который является немного многословным и может быть очень длинным при добавлении новых элементов.

abstract class A {
    static staticF<T extends A>(this: new () => T): string {
        return 'A'
    }
}

class B extends A {
    static bProp = 1
}
class C extends A {
    static cProp = 1
    static staticF<T extends A>(this: new () => T): string {
        return 'B'
    }
}

const types = [B, C]
types
    .map(t => t.staticF())
    .forEach(x => console.log(x))

Я пытался использовать const types: typeof A[], но я получаюследующая ошибка:

Контекст 'this' типа 'typeof A' не может быть назначен методу 'this' типа 'new () => A'.Невозможно назначить абстрактный тип конструктора для неабстрактного типа конструктора.

Я также пытался const types: typeof extends A[], но TS думает, что я пьян.

Как я могу выразить типынесколько конструкторов классов из классов, которые имеют одного и того же родителя?

Кроме того, в чем разница между typeof A, new () => A и {new (): A}?

1 Ответ

0 голосов
/ 16 сентября 2018

Проще всего ответить на вопрос, в чем разница между typeof A, new () => A и {new (): A}. Последние два эквивалентны, синтаксис { new() : A } является более подробным двоюродным братом new () => A. Причиной использования прежней более подробной версии является то, что она позволяет вам указывать больше перегрузок для конструктора, а также позволяет указывать дополнительные члены (то есть статические методы). typeof A - это класс A, который включает сигнатуру конструктора, а также любую статику. Если вы просто хотите создавать экземпляры класса, простая сигнатура конструктора достаточно хороша. Если вам нужен статический доступ, вам нужно typeof Class.

Что касается другой вашей проблемы, проблема в том, что машинописный текст обрабатывает конструктор абстрактного класса как бит конструктора второго класса. Это не конструктор, кроме как внутри производного класса, который, поскольку класс не должен создаваться, не является плохой идеей. В этом случае, однако, это означает, что при вызове static для A класс A не будет выполнять ограничение на наличие вызываемого конструктора (this: new () => T)

Самое простое решение, которое я нашел, - создать интерфейс, расширяющий typeof A. Это фактически стерет абстрактность конструктора и позволит вам создать нужный массив:

type AClass = (typeof A);
interface DerivedAClass extends AClass {}

let types : DerivedAClass[] = [B, C];
types
    .map(t => t.staticF()) // T of staticF will be DerivedAClass
    .forEach(x => console.log(x))

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...