Comment déclarer un type class
afin de m'assurer que l'objet est un constructeur d'une classe générale?
Dans l'exemple suivant, je veux savoir quel type dois-je donner à AnimalClass
pour qu'il soit soit Penguin
ou 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();
}
}
Bien sûr, le type class
ne fonctionne pas et serait de toute façon trop général.
Je ne sais pas si cela était possible dans TypeScript lorsque la question a été posée à l'origine, mais ma solution préférée est d'utiliser génériques:
class Zoo<T extends Animal> {
constructor(public readonly AnimalClass: new () => T) {
}
}
De cette manière, les variables penguin
et lion
déduisent le type concret Penguin
ou Lion
même dans le typeScript intellisense.
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.
Solution de référence des interfaces 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);
Ainsi, l'exemple précédent devient:
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();
}
}
Comme ça:
class Zoo {
AnimalClass: typeof Animal;
constructor(AnimalClass: typeof Animal ) {
this.AnimalClass = AnimalClass
let Hector = new AnimalClass();
}
}
Ou juste:
class Zoo {
constructor(public AnimalClass: typeof Animal ) {
let Hector = new AnimalClass();
}
}
typeof Class
est le type du constructeur de la classe. Il est préférable à la déclaration de type de constructeur personnalisé, car elle traite correctement les membres de la classe statique.
Voici la partie pertinente de Docs TypeScript . Rechercher le typeof
. Dans le cadre d'une annotation de type TypeScript, cela signifie "donnez-moi le type du symbole appelé Animal", qui est le type de la fonction constructeur de la classe dans notre cas.
Comment déclarer un type de classe afin de m'assurer que l'objet est un constructeur d'une classe générale?
Un type de constructeur peut être défini comme:
type AConstructorTypeOf<T> = new (...args:any[]) => T;
class A { ... }
function factory(Ctor: AConstructorTypeOf<A>){
return new Ctor();
}
const aInstance = factory(A);