I think you should change the annotation to the following:
function foo(subclass: new () => A) {
const obj = new subclass();
}
Here, we are saying that subclass
is new
able (i.e., it's a constructor function you call with the new
operator), takes no arguments, and constructs a value whose type is assignable to A
. This should accept any concrete subclass of A
as long as it has a no-arg constructor:
foo(B); // okay
foo(C); // okay
It won't accept A
itself, because an abstract class constructor is not considered new
able:
foo(A); // error, A is abstract
Oh, as a note for people making example TypeScript code for Stack Overflow questions: Note that TypeScript's type system is structural. With the example definitions you gave, instances of A
, B
, and C
are considered the same, empty type. And all objects are assignable to the empty type, so this also works:
foo(Date); // okay also
To prevent that, you should add properties to A
, B
, and/or C
to distinguish them structurally, such as:
abstract class A {
a = "A"
};
class B extends A {
b = "B"
};
class C extends A {
c = "C"
};
Which will result in more expected behavior:
foo(B); // okay
foo(C); // okay
foo(A); // error, A is abstract
foo(Date); // error, 'a' is missing
Okay, hope that helps; good luck!
Playground link to code