Unfortunately, as of 0.9.5, TypeScript doesn\'t (yet) have algebraic data types (union types) and pattern matching (to destructure them). What\'s more, it doesn\'t even supp
Here's an alternative to the very good answer by @thSoft. On the plus side, this alternative
{ type : string } & T
, where the shape of T
depends on the value of type
,on the negative side
It looks like this:
// One-time boilerplate, used by all cases.
interface Maybe { value : T }
interface Matcher { (union : Union) : Maybe }
interface Union { type : string }
class Case {
name : string;
constructor(name: string) {
this.name = name;
}
_ = (data: T) => ( ({ type : this.name, data : data }) )
$ =
(f:(t:T) => U) => (union : Union) =>
union.type === this.name
? { value : f((union).data) }
: null
}
function match(union : Union, destructors : Matcher [], t : T = null)
{
for (const destructor of destructors) {
const option = destructor(union);
if (option)
return option.value;
}
return t;
}
function any(f:() => T) : Matcher {
return x => ({ value : f() });
}
// Usage. Define cases.
const A = new Case("A");
const B = new Case("B");
// Construct values.
const a = A._(0);
const b = B._("foo");
// Destruct values.
function f(union : Union) {
match(union, [
A.$(x => console.log(`A : ${x}`))
, B.$(y => console.log(`B : ${y}`))
, any (() => console.log(`default case`))
])
}
f(a);
f(b);
f({});