user2503048
user2503048

Reputation: 1041

Typescript - returning the constructor of a child class from an abstract method

I have abstract class Child and abstract class Parent as follows:

abstract class Child {

}

abstract class Parent {
  abstract getChild(): typeof Child; // <-- want a class that extends Child
}

The idea is that both Parent and Child are extended by actual implementation classes, where each implementation Parent knows what its Child class is:

class ActualChild extends Child {

}

class ActualParent extends Parent {
  getChild() {
    return ActualChild;
  }
}

As far as TS is concerned, the returned object is of type Child, and thus cannot be instantiated.

I tried many different ways to explain that the function returns only a class that extends Child without success.

Is there any way to type that?

Upvotes: 1

Views: 3001

Answers (2)

Erik Philips
Erik Philips

Reputation: 54638

I think you're looking for generics and a new constaint.

abstract class Child {

}

abstract class Parent<TChild extends Child> {
  abstract getChild(): { new(): TChild}; 
}

then

class ActualChild extends Child {

}

class ActualParent extends Parent<ActualChild> {
  getChild() {
    return ActualChild;
  }
}

Typescript Playground Approves

As far as TS is concerned, the returned object is of type Child, and thus cannot be instantiated.

This is technically incorrect. The object returns is class type (the class of child). Your wording object is of type Child typically means an instantiated object of type Child which is not correct.

Upvotes: 2

Patrick Roberts
Patrick Roberts

Reputation: 51916

Declare an interface to describe the abstract class Child itself, and change the return type of getChild() to be that interface.

interface ChildConstructor {
  new(): Child;
}


abstract class Parent {
  abstract getChild(): ChildConstructor;
}

Then this will compile without TypeScript errors:

const parentInstance: Parent = new ActualParent();
const ChildClass = parentInstance.getChild();
const childInstance = new ChildClass();

Upvotes: 1

Related Questions