Как представить тип любого подкласса абстрактного класса в Typescript? - PullRequest
0 голосов
/ 07 февраля 2020

Предполагая

abstract class A {};
class B extends A {};
class C extends A {};

Я хочу принять в качестве параметра любой подкласс A.

function foo(Subclass: A){
   const obj = new Subclass();
}

Это не сработает. Я получаю ошибку

Это выражение не может быть построено. Тип «BaseController» не имеет конструктивных сигнатур.

Тогда я попытался

function foo(Subclass: typeof A){   
   const obj = new Subclass();
}

Теперь я получаю ошибку

Невозможно создать экземпляр abstract class.ts (2511)

Поскольку предполагается, что я передаю A, а не подкласс A. A. 1022 *

Это достижимо? Как мне заставить это работать?

Ответы [ 2 ]

2 голосов
/ 07 февраля 2020

Я думаю, вам следует изменить аннотацию на следующую:

function foo(subclass: new () => A) {
  const obj = new subclass();
}

Здесь мы говорим, что subclass new способен (то есть это функция конструктора Вы вызываете с оператором new), не принимает аргументов и создает значение, тип которого можно присвоить A. Это должно принять любой конкретный подкласс A, если он имеет конструктор без аргументов:

foo(B); // okay
foo(C); // okay

Он не будет принимать A сам, потому что абстрактный конструктор класса не считается new able:

foo(A); // error, A is abstract

О, как примечание для людей, делающих пример кода TypeScript для вопросов переполнения стека: Обратите внимание, что система типов TypeScript структурная . В приведенных вами примерах определений экземпляры A, B и C считаются одинаковыми, пустой . И все объекты присваиваются пустому типу , поэтому это также работает:

foo(Date); // okay also

Чтобы предотвратить это, вы должны добавить свойства в A, B и / или C различать guish их структурно, например:

abstract class A {
  a = "A"
};
class B extends A {
  b = "B"
};
class C extends A {
  c = "C"
};

, что приведет к более ожидаемому поведению:

foo(B); // okay
foo(C); // okay
foo(A); // error, A is abstract
foo(Date); // error, 'a' is missing

Хорошо, надеюсь, что помогает; удачи!

Детская площадка ссылка на код

1 голос
/ 07 февраля 2020

Чтобы это работало, вам нужно обратиться к классу по его ссылке на конструктор.

abstract class A {};
class B extends A {};
class C extends A {};

function foo(Subclass: new () => A) {   
   const obj = new Subclass();
}

В этом случае вы можете передать и B, и C в foo, так как они имеют конструкторы , A не будет принято, поскольку в абстрактном классе нет конструктора.

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