Given a Parent
class with children ChildA
ChildB
abstract class Parent {
abstract foo()
}
class ChildA extends Parent {
foo() { }
bar() { }
}
class ChildB extends Parent {
foo() { }
baz() { }
}
How can I strictly type a function's parameter as being any class (the class itself, not an instance) that conforms to the type Parent
, but is not itself Parent
fn(Parent) // Should fail, is supertype rather than subtype
fn(new ChildA()) // should fail, is instance of subtype rather than class itself
fn(new ChildB()) // should fail, is instance of subtype rather than class itself
fn(ChildA) // Should succeed
fn(ChildB) // Should succeed
You can define your fn
as the following, using a construct signature:
function fn(ctor: new (...args: any[]) => Parent) {}
This describes a constructor that creates something which extends Parent
(structurally, in the type system). Funnily enough, this is very close to the example in the documentation on abstract construct signatures.
Passing in Parent
will fail since Parent
has an abstract constructor:
fn(Parent);
// ~~~~~~ Cannot assign an abstract constructor type to a non-abstract constructor type.
It may also help to mention a method that will work even if the Parent class is not abstract. You would need to check if the given class is the Parent or not first. Thankfully, this is possible, since types are inferred before being instantiated:
function fn<Ctor extends new (...args: any[]) => Parent>(ctor: typeof Parent extends Ctor ? never : Ctor) {}