Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nrdlab/pattern-matching-ts
⚡ Pattern Matching in Typescript
https://github.com/nrdlab/pattern-matching-ts
fp fp-ts functional-programming matching option-monad pattern pattern-matching typescript typescript-pattern-matching
Last synced: 3 months ago
JSON representation
⚡ Pattern Matching in Typescript
- Host: GitHub
- URL: https://github.com/nrdlab/pattern-matching-ts
- Owner: stefano-regosa-deel
- License: mit
- Created: 2020-11-10T08:09:12.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2021-08-30T10:59:22.000Z (about 3 years ago)
- Last Synced: 2024-08-12T08:09:14.314Z (3 months ago)
- Topics: fp, fp-ts, functional-programming, matching, option-monad, pattern, pattern-matching, typescript, typescript-pattern-matching
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/pattern-matching-ts
- Size: 1.68 MB
- Stars: 187
- Watchers: 5
- Forks: 8
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-fp-ts - nrdlab/pattern-matching-ts
README
Pattern matching in Typescript.
Pattern Matching is a declarative much more powerful and less verbose alternative to imperatives "if/else" conditions.
A definition can be found inside Scala Documentation
“Pattern matching tests whether a given value (or sequence of values) has the shape defined by a pattern, and, if it does, binds the variables in the pattern to the corresponding components of the value (or sequence of values).”
In Functional Programming languages, there're built-in keywords for Pattern Matching. Typescript though is one language that works very well with Functional Programming but lacks this feature.
This package aims to bring Pattern Matching feature to Typescript through Discriminated Union Types / Algebraic Data Types.
# Index
- [Installation](#installation)
- [Usage](#usage)---
- [Match](#match)
- [Match Option](#option-match)
- [Match Default ](#default-match)
- [MatchW](#matchW)
- [MatchW Option](#option-MatchW)
- [MatchW Either](#either-MatchW)
- [MatchW Default](#default-matchW)---
- [License](#license)
# Installation
**yarn**
```sh
yarn add pattern-matching-ts
```**npm**
```sh
npm install --save pattern-matching-ts
```# Usage
**_MatchW_**
> ### Option MatchW
```ts
import * as M from 'pattern-matching-ts/lib/match'
import { pipe } from 'fp-ts/lib/function'
import * as O from 'fp-ts/lib/Option'const optionMatching = (o: unknown) =>
pipe(
o,
M.matchW('_tag')({
Some: ({ value }) => 'Something: ' + value,
None: () => 'Nothing',
_: () => 'Default'
})
)assert.deepStrictEqual(optionMatching(O.some('data')), 'Something: data')
assert.deepStrictEqual(optionMatching(O.none), 'Nothing')
assert.deepStrictEqual(optionMatching((undefined as unknown) as O.None), 'Default')
```> ### Either MatchW
```ts
import * as M from 'pattern-matching-ts/lib/match'
import { pipe } from 'fp-ts/lib/function'
import * as E from 'fp-ts/lib/Either'type RGB = Record<'r' | 'g' | 'b', number>
const either = (maybeRgb: E.Either) =>
pipe(
maybeRgb,
M.matchW('_tag')({
Left: ({ left }) => 'Error: ' + left,
Right: ({ right: { r, g, b } }) => `Red: ${r} | Green: ${g} | Blue: ${b}`
})
)assert.deepStrictEqual(either(E.right({ r: 255, g: 255, b: 0 })), 'Red: 255 | Green: 255 | Blue: 0')
```> ### Default MatchW
```ts
import * as M from 'pattern-matching-ts/lib/match'
import { pipe } from 'fp-ts/lib/function'interface ServerResponse
{
readonly code: Code
}interface Response {
readonly response: {
readonly body: Body
}
}interface Success extends ServerResponse<200>, Response> {}
interface NotFoundError extends ServerResponse<404> {}
interface ServerError extends ServerResponse<500> {
readonly detail: string
}type Responses = Success | NotFoundError | ServerError
const matchResponse = (response: Responses) =>
pipe(
response,
M.matchW('code')({
500: ({ detail }) => ({ message: 'Internal server error', detail }),
404: () => ({ message: 'The page cannot be found!' }),
200: ({ response }) => response.body,
_: () => 'Unexpected response'
})
)assert.deepStrictEqual(either(E.right({ r: 255, g: 255, b: 0 })), 'Red: 255 | Green: 255 | Blue: 0')
assert.deepStrictEqual(matchResponse({ code: 200, response: { body: ['data'] } }), ['data'])
assert.deepStrictEqual(matchResponse({ code: 500, detail: 'Cannot connect to the database' }), {
message: 'Internal server error',
detail: 'Cannot connect to the database'
})
assert.deepStrictEqual(matchResponse({ code: 404 }), { message: 'The page cannot be found!' })
```**_Match_**
> ### Option Match
```ts
import * as M from 'pattern-matching-ts/lib/match'
import * as O from 'fp-ts/lib/Option'const optionMatching = M.match, string>({
Some: (x) => `Something: ${x.value}`,
None: () => 'Nothing'
})assert.deepStrictEqual(optionMatching(O.some('data')), 'Something: data')
assert.deepStrictEqual(optionMatching(O.none), 'Nothing')
```> ### Default Match
```ts
import * as M from 'pattern-matching-ts/lib/match'interface ChangeColor {
readonly _tag: 'ChangeColor'
readonly value: {
readonly r: T
readonly g: T
readonly b: T
}
}
interface Move {
readonly _tag: 'Move'
readonly value: {
readonly x: T
readonly y: T
}
}
interface Write {
readonly _tag: 'Write'
readonly value: {
readonly text: string
}
}type Cases = ChangeColor | Move | Write
const matchMessage = M.match({
ChangeColor: ({ value: { r, g, b } }) => `Change the color to Red: ${r} | Green: ${g} | Blue: ${b}`,
Move: ({ value: { x, y } }) => `Move in the x direction: ${x} and in the y direction: ${y}`,
Write: ({ value: { text } }) => `Text message: ${text}`,
_: () => 'Default message'
})const ChangeColor = ({ r, g, b }: ChangeColor['value']): ChangeColor => ({
_tag: 'ChangeColor',
value: { r, g, b }
})const Move = ({ x, y }: Move['value']): Move => ({
_tag: 'Move',
value: { x, y }
})const Write = ({ text }: Write['value']): Write => ({
_tag: 'Write',
value: { text }
})assert.deepStrictEqual(
matchMessage(Move({ x: 500, y: 100 })),
'Move in the x direction: 500 and in the y direction: 100'
)assert.deepStrictEqual(
matchMessage(ChangeColor({ r: 12, g: 20, b: 30 })),
'Change the color to Red: 12 | Green: 20 | Blue: 30'
)assert.deepStrictEqual(matchMessage(Write({ text: 'my message' })), 'Text message: my message')
```Blog posts that introduces the API.
👉 [Pattern Matching in Typescript](https://dev.to/stefano_regosa/typescript-pattern-matching-ne8)
👉 [Pipeable Pattern Matching in Typescript](https://dev.to/stefano_regosa/pipeable-pattern-matching-in-typescript-33dn)
[MIT](/LICENSE.md)