Skip to content

Instantly share code, notes, and snippets.

@Raiondesu
Last active September 17, 2019 20:21
Show Gist options
  • Save Raiondesu/ff89a2ad0f9d4d814fb6fee0c6153824 to your computer and use it in GitHub Desktop.
Save Raiondesu/ff89a2ad0f9d4d814fb6fee0c6153824 to your computer and use it in GitHub Desktop.
Simple TypeScript pattern matching
const t1 = match(2) (_ => [
[
Number,
_ => 'number!'
],
[
_ > 3,
_ => _ + 3
],
[
_ == 2,
_ => `asdasd${_}`,
],
]);
// t1 is 'number!'
const t2 = match('2') (_ => [
[
Number,
_ => console.log('number!')
],
[
String,
_ => console.log('string!')
],
[
Boolean,
_ => console.log('boolean!')
],
]);
// t2 is undefined, logged 'string!'
export type Matcher<T> = T extends Array<any> ? [
boolean | Function | T,
(...args: T) => any
] : [
boolean | Function | T,
(arg: T) => any
];
export type Match<T = any, M extends Matcher<T>[] = Matcher<T>[]> = (_: T) => M;
export const match = <T>(thing: T) => <M extends Match<T>>(f: M): ReturnType<ReturnType<M>[number][1]> => {
const res = f(thing);
for (const n of res) {
const _ = () => n[1](thing);
const success = (false
|| n[0] === thing
|| n[0] === true
|| (typeof n[0] === 'function' && ((typeof thing === 'object' && thing instanceof n[0]) || Object(thing) instanceof n[0]))
|| (Array.isArray(n[0]) && Array.isArray(thing) && n[0].length === thing.length && thing.every((_, i) => _ === n[0][i]))
|| (typeof n[0] === 'object' && (thing === n[0] || Object.keys(n[0]).every(key => n[0][key] === thing[key])))
);
if (success) {
return _();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment