Reputation: 1041
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
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
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