Could a generic match function be defined over discriminated union type? Let's consider the following type declarations:
const Kinds = {
A: 'A',
B: 'B',
};
type Kind = typeof Kinds.A | typeof Kinds.B;
type Value = A | B;
interface A {
kind: Kinds.A
}
interface B {
kind: Kinds.B
}
While a switch statement can be used to define a match function like this:
interface Matcher<T> {
Kinds.A: (value: A) => T
Kinds.B: (value: B) => T
}
function match<T>(matcher: Matcher<T>) {
return function(value: Value) {
switch (value.kind) {
case Kinds.A: return matcher[Kinds.A](value);
case Kinds.B: return matcher[Kinds.B](value);
}
}
}
Although functional, this approach becomes cumbersome when dealing with numerous union members.
Is there a way to streamline this process, perhaps utilizing Mapped Types or other features from the latest 2.1 branch?
I experimented with "Mapped Types", but struggled to extract concrete Value based on known Kind, for example:
type Matcher<T> = {[P in Kind]: (value: P) => T};
function match<T>(matcher: Matcher<T>) {
return function(value: Value) {
return matcher[value.kind](value);
}
}
The challenge lies in translating P into its corresponding Value type.