Let's create a simple class hierarchy and a list of instances. The goal is to filter items from the list of instances based on their class.
There are a couple of challenges:
- We cannot use the
typeof T
syntax. How can this be written? - We cannot declare
T
asout
variance - we don't want to instantiate anything in the method, just return instances ofT
. How do we convey this to TypeScript?
class A {
}
class B extends A {
}
class C extends A {
}
function filterByClass<out T extends A>(cls: typeof T, list: A[]): T[]
{
return list.filter((item) => item instanceof T);
}
Edit:
The solution (by Adrian Kokot) was effective until it was realized that the example was "too simplistic". In reality, constructors have parameters, more like this:
class B extends A {
constructor(pb: any) {
super();
}
}
class C extends A {
constructor(pc: any) {
super();
}
}
Using modified playground provided in the answer, the issue with variance arises:
const a = new A();
const b = new B(1);
const c = new C(1);
const arrC = filterByClass(C, arr);
Argument of type 'typeof C' is not assignable to parameter of type 'new () => C'.
Types of construct signatures are incompatible.
Type 'new (pc: any) => C' is not assignable to type 'new () => C'.