Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to type a list of classes inheriting from the same base class?

In TypeScript I'm trying to correctly type a variable of type "Array of Classes inheriting from a base class".

Using this code I get the error 'Cannot create an instance of an abstract class. ts(2511)' which I understand. But I don't want to instantiate a member of Base, just its descendants.

abstract class Base {
  abstract execute(param: string): void;
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }

  public commonMethod() {
    console.log("Common Method");
  }
}

class A extends Base {
  execute() {
    console.log(`Hello from A, ${this.name}`);
    this.commonMethod();
  }
}

class B extends Base {
  execute() {
    console.log(`Hello from B, no-name`);
  }
}

const list: typeof Base[] = [A, B];

const names = ["Phil", "Andy", "Bob"];

names.map((name) => list.map((cl) => new cl(name)));

How would I correctly type const list: ???[] = [A, B];

When I switch to const list: typeof A[] = [A,B] it works but then suggests all list entries are A which they are not.

Playground link

like image 698
Phil Avatar asked Nov 16 '25 05:11

Phil


1 Answers

You can use a constructor signature instead of the class itself:


const list: Array<new (name: string) => Base> = [A, B];

const names = ["Phil", "Andy", "Bob"];

names.map((name) => list.map((cl) => new cl(name)));

Playground Link

This will not let you access statics, if you need those you could also use:

const list: Array<Omit<typeof Base, never> & (new (name: string) => Base)> = [A, B];

const names = ["Phil", "Andy", "Bob"];

names.map((name) => list.map((cl) => new cl(name)));
list[0].foo();

Playground Link

like image 98
Titian Cernicova-Dragomir Avatar answered Nov 17 '25 20:11

Titian Cernicova-Dragomir



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!