<I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [
never
]
? (u: I) => Unify<A>
: Unify<A>Completes a matcher that handles every remaining input case.
When to use
Use to require TypeScript to reject incomplete matcher definitions before the matcher is turned into a function.
Details
If any case is still unmatched, the matcher does not type-check as exhaustive.
Example (Ensuring all cases are covered)
import { Match } from "effect"
// Create a matcher for string or number values
const match = Match.type<string | number>().pipe(
// Match when the value is a number
Match.when(Match.number, (n) => `number: ${n}`),
// Mark the match as exhaustive, ensuring all cases are handled
// TypeScript will throw an error if any case is missing
// @ts-expect-error Type 'string' is not assignable to type 'never'
Match.exhaustive
)export const const exhaustive: <I, F, A, Pr, Ret>(
self: Matcher<I, F, never, A, Pr, Ret>
) => [Pr] extends [never]
? (u: I) => Unify<A>
: Unify<A>
Completes a matcher that handles every remaining input case.
When to use
Use to require TypeScript to reject incomplete matcher definitions before the
matcher is turned into a function.
Details
If any case is still unmatched, the matcher does not type-check as
exhaustive.
Example (Ensuring all cases are covered)
import { Match } from "effect"
// Create a matcher for string or number values
const match = Match.type<string | number>().pipe(
// Match when the value is a number
Match.when(Match.number, (n) => `number: ${n}`),
// Mark the match as exhaustive, ensuring all cases are handled
// TypeScript will throw an error if any case is missing
//
exhaustive: <function (type parameter) I in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>I, function (type parameter) F in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>F, function (type parameter) A in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>A, function (type parameter) Pr in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>Pr, function (type parameter) Ret in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>Ret>(
self: Matcher<I, F, never, A, Pr, Ret>self: type Matcher<
Input,
Filters,
RemainingApplied,
Result,
Provided,
Return = any
> =
| TypeMatcher<
Input,
Filters,
RemainingApplied,
Result,
Return
>
| ValueMatcher<
Input,
Filters,
RemainingApplied,
Result,
Provided,
Return
>
Union type for matchers created by Match.type and Match.value.
Details
A Matcher carries the input type, accumulated filters, remaining cases,
result type, and, for value matchers, the provided value being matched.
Example (Matching string and number values)
import { Match } from "effect"
// Simulated dynamic input that can be a string or a number
const input: string | number = "some input"
// ┌─── string
// ▼
const result = Match.value(input).pipe(
// Match if the value is a number
Match.when(Match.number, (n) => `number: ${n}`),
// Match if the value is a string
Match.when(Match.string, (s) => `string: ${s}`),
// Ensure all possible cases are covered
Match.exhaustive
)
console.log(result)
// Output: "string: some input"
Matcher<function (type parameter) I in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>I, function (type parameter) F in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>F, never, function (type parameter) A in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>A, function (type parameter) Pr in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>Pr, function (type parameter) Ret in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>Ret>
) => [function (type parameter) Pr in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>Pr] extends [never] ? (u: Iu: function (type parameter) I in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>I) => type Unify<A> = Values<ExtractTypes<FilterIn<A> & {
[typeSymbol]: A;
}>> extends infer Z ? Z | FilterInUnmatched<A, Keys<ExtractTypes<FilterIn<A> & {
[typeSymbol]: A;
}>>> | FilterOut<A> : never
Unifies types that implement the unification protocol.
When to use
Use to normalize unions of types that expose Effect's unification protocol.
Details
This type performs automatic type unification for types that contain
the unification symbols (unifySymbol, typeSymbol, ignoreSymbol).
It's primarily used internally by the Effect type system to handle
complex type unions and provide better type inference.
Example (Unifying protocol types)
import type { Unify } from "effect"
// Example of types that can be unified
type UnifiableA = {
value: string
[Unify.typeSymbol]?: string
[Unify.unifySymbol]?: { String: () => string }
}
type UnifiableB = {
value: number
[Unify.typeSymbol]?: number
[Unify.unifySymbol]?: { Number: () => number }
}
// Unify automatically handles the union
type Unified = Unify.Unify<UnifiableA | UnifiableB>
// Results in a properly unified type
Unify<function (type parameter) A in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>A> : type Unify<A> = Values<ExtractTypes<FilterIn<A> & {
[typeSymbol]: A;
}>> extends infer Z ? Z | FilterInUnmatched<A, Keys<ExtractTypes<FilterIn<A> & {
[typeSymbol]: A;
}>>> | FilterOut<A> : never
Unifies types that implement the unification protocol.
When to use
Use to normalize unions of types that expose Effect's unification protocol.
Details
This type performs automatic type unification for types that contain
the unification symbols (unifySymbol, typeSymbol, ignoreSymbol).
It's primarily used internally by the Effect type system to handle
complex type unions and provide better type inference.
Example (Unifying protocol types)
import type { Unify } from "effect"
// Example of types that can be unified
type UnifiableA = {
value: string
[Unify.typeSymbol]?: string
[Unify.unifySymbol]?: { String: () => string }
}
type UnifiableB = {
value: number
[Unify.typeSymbol]?: number
[Unify.unifySymbol]?: { Number: () => number }
}
// Unify automatically handles the union
type Unified = Unify.Unify<UnifiableA | UnifiableB>
// Results in a properly unified type
Unify<function (type parameter) A in <I, F, A, Pr, Ret>(self: Matcher<I, F, never, A, Pr, Ret>): [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>A> = import internalinternal.const exhaustive: <I, F, A, Pr, Ret>(
self: Matcher<I, F, never, A, Pr, Ret>
) => [Pr] extends [never]
? (u: I) => Unify<A>
: Unify<A>
exhaustive