Тип Class<?> для абстрактных классов в TypeScript

В TypeScript я использую Java как тип Class:

interface Class<T = void> {

    new(...args: any[]): T;

}

Однако такой тип не работает с абстрактными классами:

abstract class Bar {}

class Foo {
   
  test(clazz: Class) { }

  doIt() {
    this.test(Bar);//ERROR
  }
}

Я получаю ошибку Argument of type 'typeof Bar' is not assignable to parameter of type 'Class<void>'. Когда класс Bar не абстрактный, то все в порядке.

Я понимаю, что проблема в том, что объявляя Class, мы говорим, что можно использовать оператор new, но мы не можем использовать этот оператор для абстрактных классов. Однако мне нужен тип, который мог бы подойти как для неабстрактных, так и для абстрактных классов (абстрактные классы тоже являются классами). Если это возможно, может ли кто-нибудь сказать, как это сделать?


2
21
1

Ответ:

Решено

Вы можете использовать abstract создать подпись:

type Class<T = void> =
  abstract new (...args: any[]) => T;

Вы можете присвоить такой подписи как обычный/конкретный конструктор, так и конструктор abstract по желанию:

abstract class Bar { }
class Baz { }

class Foo {

  test(clazz: Class) { }

  doIt() {
    this.test(Bar); // okay
    this.test(Baz); // okay
  }
}

Обратите внимание, что по какой-либо причине сигнатуры конструкции abstract должны быть в форме выражения конструкции стрелки (например, функциональное выражение); вы не можете поставить abstract перед new в сигнатуре объектной конструкции:

interface Oops<T = void> {
  abstract new(...args: any[]): T; // error!
  //~~~~~~ <-- 'abstract' modifier cannot appear on a type member
}

Ссылка на код для игровой площадки