https://github.com/dkendal/match-ts
Pattern matching for Javascript
https://github.com/dkendal/match-ts
javascript matching nodejs nodejs-library pattern pattern-matching typescript typescript-library
Last synced: 8 months ago
JSON representation
Pattern matching for Javascript
- Host: GitHub
- URL: https://github.com/dkendal/match-ts
- Owner: Dkendal
- Created: 2021-09-16T05:48:51.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2022-01-23T01:41:58.000Z (almost 4 years ago)
- Last Synced: 2025-04-15T06:51:26.404Z (8 months ago)
- Topics: javascript, matching, nodejs, nodejs-library, pattern, pattern-matching, typescript, typescript-library
- Language: TypeScript
- Homepage:
- Size: 185 KB
- Stars: 25
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: Changelog.md
Awesome Lists containing this project
README
# @dkendal/match
Provides pattern matching features typically found in functional
languages like Elixir/Erlang, ML, F\#, etc.
## Installation
```sh
yarn add @dkendal/match
```
## The `match` function
The match function lets us compare a value against many patterns until
we find one that matches.
```typescript
import { __, match, when } from '@dkendal/match'
match(
[1, 2, 3],
when([4, 5, 6], () => "This clause won't match"),
when([1, __, 3], () => 'This clause will match, __ will match any value'),
when(__, () => 'This clause would match any value'),
)
'This clause will match, __ will match any value'
```
The value that was passed into `match` is also passed to the callback:
```typescript
const x = 10
match(
x,
when(__, (value) => value * 10),
)
100
```
If none of the cases match and error is thrown:
```typescript
match([1, 2, 3]
when([1, 2], () => "this won't match as the array lengths don't agree"))
// (Error) unmatched case: [1, 2, 3]
```
## The `when` function
The `when` function exists purely for typing. When you use it gives the callback
the proper type expressed in the left-hand-side pattern:
```typescript
when(
V('checkout', {
type: 'checkout',
lineItems: [V('firstLineItem', { type: 'line_item', data: __ }), __.rest],
}),
({ checkout, firstLineItem }) => {
var checkout: {
type: 'checkout'
id: number
lineItems: [{
type: 'line_item'
id: number
data: any
}, any[]]
}
var firstLineItem: {
type: 'line_item'
id: number
data: any
}
},
)
```
## `match` function continued
Array's are matched as tuples, the lengths have to be the same:
```typescript
match([1, 2, 3]
when([1, 2], () => "this won't match"),
when([1, 2, 3], () => "this will match"))
"this will match"
```
The tail of a list can be matched with `__.rest`, or it's aliases
`__.tail` or `__.tl`:
```typescript
match(
range(50, 100),
when([50, 51, __.rest], () => 'this will match'),
)
;('this will match')
```
Primitive types can be matched with special operators:
```typescript
const thingy: {
data: {
someNumber: 1
metadata: { foobar: 'foobar' }
someOtherProp: {}
}
list: [1, 2, 3]
}
match(
thingy,
when(
{
data: { someNumber: __.number, metadata: __.object },
list: [__, __.rest],
},
() => 'this will match',
),
)
;('this will match')
```
You can capture variables and use them on the right hand side of match, if you
use `when` the callback will be typed with all variable bindings:
```typescript
const thingy: {
meta: {
type: 'contrived example',
x: 1,
y: 2,
},
data: {
a: {
b: {
c: {
d: {
message: 'hello world'
value: 42
}
}
}
}
}
}
match(thingy,
when({ meta: V('x'),
data: { a: { b: { c: { d: { value: V('y') } } } } }
}, (captures) => captures))
{
x: {
type: 'contrived example',
x: 1,
x: 2,
}
y: 42
}
```
Variable captures can also apply a pattern that must also match for the
case.
```typescript
import { match, __, V } from "pattern-matching"
const checkout = {
object: "list",
data: [
{
id: "li_1",
object: "item",
...
},
{...},
{...}
]
}
match(value,
when( { object: 'list',
data: V('data')([
V('first')({ object: 'item' }),
__.rest
])
}, (captures) => captures ))
{
data: [
{
id: "li_1",
object: "item",
...
},
{...},
{...}
]
first: {
id: "li_1",
object: "item",
...
},
}
```
## TODOs
- [ \] Proper type inference right-hand-side of match case
- [ \] Exhaustive type check for match cases