Cec
Cec

Reputation: 1826

typescript method with type as parameter

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

Answers (3)

user2347763
user2347763

Reputation: 489

export class Container<T extends typeof A> {
    public klazzes: T[];
}

enter image description here

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'

enter image description here

Upvotes: 0

Niladri
Niladri

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

Working demo

Upvotes: 0

Oscar Paz
Oscar Paz

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

Related Questions