One of widely used functional programming feature is pattern matching. Unfortunately there is no language support for it yet in TypeScript - that’s when libraries comes to rescue and this is my take on it.
Library consists of two main components:
Matcher is a function which checks that input value matches representing type:
Matching DSL consists of
caseWhen functions, used to compose matchers with case handlers,
and few aliases to make code more readable:
match(...cases) takes a variable list of
type MatchCase<T> = (val: any) => CaseResult<T> arguments
and returns first matching result or throws an error if none matched.
caseWhen(matcher)(fn) is used to build
MatchCase<T> instances, using
TypeMatcher<T> and handler functions.
To handle default case - use
npm install --save typematcher
Match exact values
Ensure input value matches defined enum:
Match object fields
Ensure input object has all fields defined by your custom type:
Ensure all array values match given type:
Library defines matchers for
isTuple10, this ought to be enough for anybody :).
You can provide you own matcher implementations compatible with
When you have highly performance-sensitive code you may pre-build matcher and save some CPU cycles:
Check source code for all defined matchers: https://github.com/lostintime/node-typematcher/blob/master/src/lib/index.ts.
Case handlers type variance
Avoid explicitly setting argument type in
caseWhen() handler function, let type inferred by compiler.
You may set more specific type, but check will bring you more general one and compiler will not fail.
This is caused by TypeScript Function Parameter Bivariance
UPD: Typescript v2.6 brings
--strictFunctionTypes compiler option and if it’s on, for this code:
you will now get this error:
caseDefault at the end
match will execute all cases as provided, so first matching will return,
- TypeMatcher source code
- TypeMatcher npm package
- Pattern Matching Support - TypeScript language support proposal
- ECMAScript Pattern Matching Syntax - ES language support proposal
- Support some non-structural (nominal) type matching in TypeScript