Тип конструктора классов в typescript?
Как я могу объявить тип class
, чтобы гарантировать, что объект является конструктором общего класса?
В следующем примере я хочу знать, какой тип я должен указывать на AnimalClass
, чтобы он мог быть Penguin
или Lion
:
class Animal {
constructor() {
console.log("Animal");
}
}
class Penguin extends Animal {
constructor() {
super();
console.log("Penguin");
}
}
class Lion extends Animal {
constructor() {
super();
console.log("Lion");
}
}
class Zoo {
AnimalClass: class // AnimalClass could be 'Lion' or 'Penguin'
constructor(AnimalClass: class) {
this.AnimalClass = AnimalClass
let Hector = new AnimalClass();
}
}
Конечно, тип class
не работает, и в любом случае он будет слишком общим.
Ответы
Ответ 1
Я не уверен, было ли это возможно в TypeScript, когда вопрос был задан изначально, но я предпочел решение с использованием обобщений:
class Zoo<T extends Animal> {
constructor(public readonly AnimalClass: new () => T) {
}
}
Таким образом, переменные penguin
и lion
выводят конкретный тип Penguin
или Lion
даже в IntelliSense TypeScript.
const penguinZoo = new Zoo(Penguin);
const penguin = new penguinZoo.AnimalClass(); // 'penguin' is of 'Penguin' type.
const lionZoo = new Zoo(Lion);
const lion = new lionZoo.AnimalClass(); // 'lion' is 'Lion' type.
Ответ 2
Решение typescript ссылок на ссылки:
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
Итак, предыдущий пример:
interface AnimalConstructor {
new (): Animal;
}
class Animal {
constructor() {
console.log("Animal");
}
}
class Penguin extends Animal {
constructor() {
super();
console.log("Penguin");
}
}
class Lion extends Animal {
constructor() {
super();
console.log("Lion");
}
}
class Zoo {
AnimalClass: AnimalConstructor // AnimalClass can be 'Lion' or 'Penguin'
constructor(AnimalClass: AnimalConstructor) {
this.AnimalClass = AnimalClass
let Hector = new AnimalClass();
}
}
Ответ 3
Вот так:
class Zoo {
AnimalClass: typeof Animal;
constructor(AnimalClass: typeof Animal ) {
this.AnimalClass = AnimalClass
let Hector = new AnimalClass();
}
}
Или просто:
class Zoo {
constructor(public AnimalClass: typeof Animal ) {
let Hector = new AnimalClass();
}
}
typeof Class
- это тип конструктора класса. Это предпочтительнее объявления типа пользовательского конструктора, потому что оно обрабатывает статические члены класса должным образом.
Здесь соответствующая часть документов TypeScript. Найдите typeof
. Как часть аннотации типа TypeScript, это означает "дайте мне тип символа с именем Animal", который является типом функции конструктора класса в нашем случае.
Ответ 4
Как я могу объявить тип класса, чтобы убедиться, что объект является конструктором общего класса?
Тип конструктора может быть определен как:
type AConstructorTypeOf<T> = new (...args:any[]) => T;
class A { ... }
function factory(Ctor: AConstructorTypeOf<A>){
return new Ctor();
}
const aInstance = factory(A);