@kklm/pattern-match
v1.0.2
Published
Pattern matching is a feature built in into many programming languages. Sadly it's not included in JavaScript nor TypeScript. It's like a `switch` statement on steroids, that lets you write a more declarative code.
Downloads
9
Readme
Typescript Pattern Matching
Pattern matching is a feature built in into many programming languages. Sadly it's not included in JavaScript nor TypeScript. It's like a switch
statement on steroids, that lets you write a more declarative code.
This library aims to implement a pattern matching system that works well with other aspects of TS. It uses Builder Pattern to get all the cases and evaluate them. The default case is mandatory.
Installation
Install it using npm (or yarn).
npm install @kklm/pattern-match
It can be imported then in your *.ts files.
import match, { AnyNumber, AnyString } from '@kklm/pattern-match'
// (...)
// with default matcher
match<any, string>(x)
.case(AnyNumber, () => '...')
.case(AnyString, () => '...')
.default(() => '...')
// with unsafe unwrap
match<any, string>(x)
.case(AnyNumber, () => '...')
.case(AnyString, () => '...')
.unwrap()
// convert to Option monad
match<any, string>(x)
.case(AnyNumber, () => '...')
.case(AnyString, () => '...')
.toOption()
// convert to ResultMonad
match<any, string>(x)
.case(AnyNumber, () => '...')
.case(AnyString, () => '...')
.toResult()
Comparison with other languages
Scala
import scala.util.Random
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
Elm
patternMatching : Int -> String
patternMatching x =
case x of
0 -> "zero"
1 -> "one"
2 -> "two"
_ -> "other"
Typescript with this library
const x = Math.floor(Math.random() * 10);
match(x)
.case(0, () => 'zero')
.case(1, () => 'one')
.case(2, () => 'two')
.default(() => 'other')
Examples
Simple value based pattern matching
const result = match(5)
.case(1, () => 'one')
.case(3, () => 'three')
.case(5, () => 'five')
.default(x => `The value is ${x}`)
result // 'five'
Partial pattern matching on objects
const result = match(anObject)
.case({ loading: true }, () => 'Loading...')
.case({ data: true }, () => 'Data received')
.default(() => 'Default state')
Partial pattern matching with Any matchers
const result = match(anObject)
.case({ loading: true }, () => 'Loading...')
.case({ data: AnyObject }, () => 'Data received')
.case({ error: AnyObject }, () => 'Error!')
.default(() => 'Default state')
Typesafe JSON parsing
When parsing JSON strings we do not know if the result will be correctly typed.
interface User {
name: string
age: number
}
const jsonString = '{ "definetly": "not an user" }'
const user = JSON.parse(jsonString) as User
user.name // runtime boom
interface User {
name: string
age: number
}
const jsonString = '{ "definetly": "not an user" }'
const user = match<unknown, User>(JSON.parse(jsonString))
.case({ name: AnyString, age: AnyNumber }, (user: unknown) => user as User)
.toResult()
user.match({
Ok: user => "user parsed correctly",
Err: _err => "handle parse error"
})