I have two classes, A and B, a predicate function for each of these classes (isA and isB), and an array arr
which holds a couple of instances of these two classes. When filtering the array using the predicate function it correctly returns just the requested instances and on the type level reduces to an array of just the requested class:
class A { }
class B { }
const isA = (
x: any
): x is A => {
return x instanceof A;
};
const isB = (
x: any
): x is B => {
return x instanceof B;
};
const arr: Array<A | B> = [new A(), new A(), new B()]
const onlyA = arr.filter(isA) // correct type: const onlyA: A[]
const onlyB = arr.filter(isB) // correct type: const onlyB: B[]
My goal is to write a function getInstance()
that takes an array with string values "a" and/or "b" and returns only the instances of this/these name(s), e.g. getInstance(["a"])
should have the same return value as onlyA
above, and getInstance(["a", "b"])
should return instances of A and B and on the type level (A | B)[]
.
I tried to create a new object Obj
that relates the strings to the predicate functions. I make getInstance()
generic and constrain its only argument to the keys of Obj
. However, this implementation doesn’t work on the type level.
const Obj = {
a: isA,
b: isB
}
const getInstance = <T extends keyof typeof Obj>(types: T[]) => {
const fns = types.map(type => Obj[type])
const set = fns.map(fn => arr.filter(() => fn))
return set.flat(1)
}
const retA = getInstance(["a"]) // wrong return type: (A | B)[]; should return A[]
const retAB = getInstance(["a", "b"]) // should return (A | B)[]
2
Answers
There is new feature in TS5 called const Type Parameters
Note a few amendments:
Playground link