Description
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.
pattern-matching-ts alternatives and similar modules
Based on the "Functional Programming" category.
Alternatively, view Index alternatives based on common mentions on social networks and blogs.
-
immutable
Immutable persistent data collections for Javascript which increase efficiency and simplicity. -
RxJS
DISCONTINUED. Functional reactive library for transforming, composing, and querying various kinds of data. -
mori
ClojureScript's persistent data structures and supporting API from the comfort of vanilla JavaScript -
Folktale
A suite of libraries for generic functional programming in JavaScript that allows you to write elegant, modular applications with fewer bugs, and more reuse.
CodeRabbit: AI Code Reviews for Developers
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of pattern-matching-ts or a related project?
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
yarn
yarn add pattern-matching-ts
npm
npm install --save pattern-matching-ts
Usage
MatchW
Option MatchW
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
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<string, RGB>) =>
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
import * as M from 'pattern-matching-ts/lib/match'
import { pipe } from 'fp-ts/lib/function'
interface ServerResponse<Code extends string | number> {
readonly code: Code
}
interface Response<Body> {
readonly response: {
readonly body: Body
}
}
interface Success extends ServerResponse<200>, Response<ReadonlyArray<string>> {}
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
import * as M from 'pattern-matching-ts/lib/match'
import * as O from 'fp-ts/lib/Option'
const optionMatching = M.match<O.Option<string>, string>({
Some: (x) => `Something: ${x.value}`,
None: () => 'Nothing'
})
assert.deepStrictEqual(optionMatching(O.some('data')), 'Something: data')
assert.deepStrictEqual(optionMatching(O.none), 'Nothing')
Default Match
import * as M from 'pattern-matching-ts/lib/match'
interface ChangeColor<T = number> {
readonly _tag: 'ChangeColor'
readonly value: {
readonly r: T
readonly g: T
readonly b: T
}
}
interface Move<T = number> {
readonly _tag: 'Move'
readonly value: {
readonly x: T
readonly y: T
}
}
interface Write {
readonly _tag: 'Write'
readonly value: {
readonly text: string
}
}
type Cases = ChangeColor<number> | Move | Write
const matchMessage = M.match<Cases, string>({
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<number>['value']): ChangeColor<number> => ({
_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
*Note that all licence references and agreements mentioned in the pattern-matching-ts README section above
are relevant to that project's source code only.