Match overview
Simple matcher that can only match against predicates and refinements. Fast and simple but sufficient for most use cases. As the matcher is so simple, it needs no compilation which really simplifies its use.
Table of contents
Constructors
make
Builds a new matcher
Signature
export declare const make: <Input>(input: Input) => Type<Input, never, Input>
Guards
has
Type guard
Signature
export declare const has: (u: unknown) => u is Type<unknown, unknown, unknown>
Models
Type (interface)
Type that represents a matcher
Signature
export interface Type<out Input, out Output, out Rest extends Input>
extends Inspectable.Inspectable,
Pipeable.Pipeable {
/** The input to match */
readonly input: Input
/** The output of the matcher when it has been found */
readonly output: Option.Option<Output>
/** @internal */
readonly [_TypeId]: {
readonly _Input: Types.Covariant<Input>
readonly _Output: Types.Covariant<Output>
readonly _Rest: Types.Covariant<Rest>
}
}
moduleTag
Module tag
Signature
export declare const moduleTag: "@parischap/effect-lib/Match/"
Utils
exhaustive
Returns the output of the matcher and shows a type error if Rest
is not never
Signature
export declare const exhaustive: <Input, Output>(self: Type<Input, Output, never>) => Output
Example
import { MMatch, MTypes } from "@parischap/effect-lib"
import { pipe } from "effect"
const handlePrimitive = (value: MTypes.Primitive) => value
const handleNonPrimitive = (value: MTypes.NonPrimitive) => value
export const testMatcher = (value: MTypes.Unknown) =>
pipe(
value,
MMatch.make,
MMatch.when(MTypes.isPrimitive, handlePrimitive),
MMatch.when(MTypes.isNonPrimitive, handleNonPrimitive),
MMatch.exhaustive
)
orElse
Returns self.output
if self
already has an output. Otherwise, returns the result of f applied to self.input
.
Signature
export declare const orElse: <Input, Rest extends Input, Output1>(
f: (value: NoInfer<Rest>) => Output1
) => <Output>(self: Type<Input, Output, Rest>) => Output | Output1
tryFunction
Returns a copy of self
if self
already has an output. Otherwise, tries f
on self.input
and matches if f
returns a some
whose value becomes the output of the matcher. Returns a copy of self
if f
returns a none
. From a type perspective, the Rest
will not be refined.
Signature
export declare const tryFunction: <Input, Rest extends Input, Output1>(
f: (value: NoInfer<Rest>) => Option.Option<Output1>
) => <Output>(self: Type<Input, Output, Rest>) => Type<Input, Output | Output1, Rest>
Example
import { MMatch } from "@parischap/effect-lib"
import { pipe, Array } from "effect"
export const testMatcher = (value: ReadonlyArray<number>) =>
pipe(
value,
MMatch.make,
MMatch.tryFunction(Array.get(1)),
MMatch.tryFunction(Array.get(5)),
MMatch.orElse(() => 0)
)
unsafeWhen
Same as orElse but we pass a predicate (useless from a javascript perspective) to tell the compiler what Rest
should be. Useful when we know better than Typescript.
Signature
export declare const unsafeWhen: <Input, Rest extends Input, Refined extends Rest, Output1>(
_predicate: Predicate.Refinement<Rest, Refined>,
f: (value: NoInfer<Refined>) => Output1
) => <Output>(self: Type<Input, Output, Rest>) => Output | Output1
Example
import { MMatch, MTypes } from "@parischap/effect-lib"
import { pipe } from "effect"
const handlePrimitive = (value: MTypes.Primitive) => value
const handleNonPrimitive = (value: MTypes.NonPrimitive) => value
export const testMatcher = (value: MTypes.Unknown) =>
pipe(
value,
MMatch.make,
MMatch.when(MTypes.isNonPrimitive, handleNonPrimitive),
MMatch.unsafeWhen(MTypes.isPrimitive, handlePrimitive)
)
when
Matches against a refinement or a predicate. Returns a copy of self
if self
already has an output. Otherwise, applies the predicate/refinement to self.input
. Returns a copy of self
if the predicate returns false
. Otherwise, returns a copy of self
with the output set to f(self.input)
. From a type perspective, the Rest is only refined
if the predicate is a refinement.
Signature
export declare const when: {
<Input, Rest extends Input, Refined extends Rest, Output1>(
predicate: Predicate.Refinement<NoInfer<Rest>, Refined>,
f: (value: Refined) => Output1
): <Output>(self: Type<Input, Output, Rest>) => Type<Input, Output | Output1, Exclude<Rest, Refined>>
<Input, Rest extends Input, Output1>(
predicate: Predicate.Predicate<NoInfer<Rest>>,
f: (value: Rest) => Output1
): <Output>(self: Type<Input, Output, Rest>) => Type<Input, Output | Output1, Rest>
}
Example
import { MMatch, MTypes } from "@parischap/effect-lib"
import { pipe } from "effect"
const handlePrimitive = (value: MTypes.Primitive) => value
const handleNonPrimitive = (value: MTypes.NonPrimitive) => value
export const testMatcher = (value: MTypes.Unknown) =>
pipe(
value,
MMatch.make,
MMatch.when(MTypes.isPrimitive, handlePrimitive),
MMatch.when(MTypes.isNonPrimitive, handleNonPrimitive),
MMatch.exhaustive
)
whenAnd
Same as when but several predicates can be provided. The match occurs if all the predicates return true
. From a type perspective, the Rest
will only be refined if all predicates are refinements.
Signature
export declare const whenAnd: <
Input,
Rest extends Input,
R extends MTypes.ReadonlyOverTwo<Predicate.Predicate<Rest>>,
Output1
>(
...args: readonly [
...refinements: R,
f: (
value: NoInfer<MTypes.IntersectAndSimplify<MTypes.ToKeyIntersection<MPredicate.PredicatesToTargets<R>>, Rest>>
) => Output1
]
) => <Output>(
self: Type<Input, Output, Rest>
) => Type<Input, Output | Output1, Exclude<Rest, MTypes.ToKeyIntersection<MPredicate.PredicatesToCoverages<R>>>>
whenIs
Matches against a primitive value sparing you the need to define a type guard. Returns a copy of self
if self
already has an output. Otherwise, self.input
is compared to the provided value using strict equality. Returns a copy of self
if the two values are not equal. Otherwise, returns a copy of self with the output set to the result of f(self.input)
. From a type perspective, the Rest will only be ‘refined if it
s a finite type like an Enum (but not number
or string
)
Signature
export declare const whenIs: <Input extends MTypes.Primitive, Rest extends Input, const A extends Rest, Output1>(
value: A,
f: (value: A) => Output1
) => <Output>(self: Type<Input, Output, Rest>) => Type<Input, Output | Output1, Exclude<Rest, A>>
Example
import { MMatch } from "@parischap/effect-lib"
import { pipe } from "effect"
enum TestEnum {
A = `a`,
B = `b`,
C = `c`
}
export const testMatcher = (value: TestEnum) =>
pipe(
value,
MMatch.make,
MMatch.whenIs(TestEnum.A, () => `a`),
MMatch.whenIs(TestEnum.B, () => `b`),
MMatch.whenIs(TestEnum.C, () => `c`),
MMatch.exhaustive
)
whenIsOr
Same as whenIs but you can pass several values to match against.
Signature
export declare const whenIsOr: <
Input extends MTypes.Primitive,
Rest extends Input,
R extends MTypes.ReadonlyOverTwo<Rest>,
Output1
>(
...args: readonly [...values: R, f: (value: R[number]) => Output1]
) => <Output>(self: Type<Input, Output, Rest>) => Type<Input, Output | Output1, Exclude<Rest, R[number]>>
Example
import { MMatch } from "@parischap/effect-lib"
import { pipe } from "effect"
enum TestEnum {
A = `a`,
B = `b`,
C = `c`
}
export const testMatcher = (value: TestEnum) =>
pipe(
value,
MMatch.make,
MMatch.whenIs(TestEnum.A, () => `a`),
MMatch.whenIs(TestEnum.B, () => `b`),
MMatch.whenIs(TestEnum.C, () => `c`),
MMatch.exhaustive
)
whenOr
Same as when but several predicates can be provided. The match occurs if one of the predicate returns true
. From a type perspective, the Rest
will only be refined if all predicates are refinements.
Signature
export declare const whenOr: <
Input,
Rest extends Input,
R extends MTypes.ReadonlyOverTwo<Predicate.Predicate<Rest>>,
Output1
>(
...args: readonly [
...refinements: R,
f: (value: NoInfer<MTypes.IntersectAndSimplify<MPredicate.PredicatesToTargets<R>[number], Rest>>) => Output1
]
) => <Output>(
self: Type<Input, Output, Rest>
) => Type<Input, Output | Output1, Exclude<Rest, MPredicate.PredicatesToCoverages<R>[number]>>