Reputation: 1826
Given this class hierarhcy
export class A {
static m() { return 'a'};
}
export class B extends A {
static m() { return 'b'};
}
export class C extends A {
static m() { return 'c'};
}
I need a method taking an array of classes (not instance) extending A
and calls m()
on each element of the array:
function looper(classes: A[]) {
classes.forEach(c => c.m());
}
This expects an array of instances of A or its subclasses.
How can I have a method that takes as argument classes that extend A?
Generics as pointed out by @Oscar Paz
EDIT 1
Moreover the input to looper needs to be stored in a property of an object:
export class Container {
public klazzes: A[];
}
Upvotes: 7
Views: 16910
Reputation: 489
export class Container<T extends typeof A> {
public klazzes: T[];
}
is not the same as
export class Container<T extends typeof A> {
public klazzes: A[];
}
Typing the array as a specific type 'A' undermines the purpose of generics. so, I guess you would want to use the template type 'T'
Upvotes: 0
Reputation: 5962
Not sure if this is something you were looking for - on top of what @Oscar suggested you can create a generic class to store the array in a property of type T[]
like below .
export class A {
static m() { return 'a'};
}
export class B extends A {
static m() { return 'b'};
}
export class C extends A {
static m() { return 'c'};
}
export class Container<T extends typeof A> {
public klazzes: T[];
constructor() {
this.klazzes = [];
}
public callM<T extends typeof A>(arr: T[]): void {
arr.forEach(t =>
console.log(t.m())
);
}
}
// usage
let cont = new Container();
cont.klazzes = [A, B, C];
cont.callM(cont.klazzes);
Here is a working link
Upvotes: 0
Reputation: 18322
Well, using generics:
function callM<T extends typeof A>(arr: T[]): void {
arr.forEach(t => t.m());
}
Now you can do:
callM([A, B, C]); // OK
callM([A, B, string]); // Error
If you want to store the values:
class Container {
public klazzes: (typeof A)[];
}
const cont: Container = new Container();
callM(cont.klazzes);
Upvotes: 6