/** * Builds pattern matchers for TypeScript values. * * `Match` lets you add ordered cases and then finish them with a result, * fallback, `Option`, or exhaustive check. Use `Match.type` to define a * reusable matcher for a type, or `Match.value` to match one value immediately. * Cases can match literal values, predicates, object shapes, tags, negated * patterns, and common checks such as strings, numbers, records, and class * instances. * * @stability stable * @since 4.0.0 */ import * as internal from "./internal/matcher.ts" import type * as Option from "./Option.ts" import type { Pipeable } from "./Pipeable.ts" import * as Predicate from "./Predicate.ts" import type * as Result from "./Result.ts" import type * as T from "./Types.ts" import type { Unify } from "./Unify.ts" const TypeId = internal.TypeId // The conditional must stay deferred until P is inferred. Replacing it with an // intersection loses contextual typing for nested generic calls (microsoft/TypeScript#52864). type Contextual
= [P] extends [never] ? Fallback : P
type TagHandlers >): (input: I) => Unify >): Unify , f: Fn]
) => (
self: Matcher
) => Matcher<
I,
Types.AddWithout >
) => (
self: Matcher
) => Matcher<
I,
Types.AddWithout ,
Pr,
Ret
> = internal.discriminators
/**
* Matches values by a discriminator field and requires every possible case to
* be handled.
*
* **When to use**
*
* Use to define an exhaustive discriminator handler map that finalizes the
* matcher.
*
* **Details**
*
* This is the exhaustive variant of {@link discriminators}. Each possible
* discriminator value must have a corresponding handler, so the matcher is
* finalized directly and does not require `Match.exhaustive` at the end of the
* pipeline.
*
* **Example** (Handling all discriminator cases)
*
* ```ts import.meta.vitest
* import { Match, pipe } from "effect"
*
* const match = pipe(
* Match.type<
* { type: "A"; a: string } | { type: "B"; b: number } | {
* type: "C"
* c: boolean
* }
* >(),
* Match.discriminatorsExhaustive("type")({
* A: (a) => a.a,
* B: (b) => b.b,
* C: (c) => c.c
* })
* )
* match({ type: "C", c: true }) // => true
* ```
*
* @see {@link discriminators} for defining discriminator handlers without finalizing the matcher
*
* @stability stable
* @category defining patterns
* @since 4.0.0
*/
export const discriminatorsExhaustive: >
) => (
self: Matcher
) => [Pr] extends [never] ? (u: I) => Unify> : Unify> =
internal.discriminatorsExhaustive
/**
* Matches discriminated union members by their `_tag` field.
*
* **When to use**
*
* Use to handle one or more `_tag` cases with the same matcher branch.
*
* **Details**
*
* This helper follows the Effect convention that discriminated unions use
* `"_tag"` as their discriminator field. Use {@link discriminator} for a
* different discriminator field.
*
* **Example** (Matching a discriminated union by tag)
*
* ```ts import.meta.vitest
* import { Match } from "effect"
*
* type Event =
* | { readonly _tag: "fetch" }
* | { readonly _tag: "success"; readonly data: string }
* | { readonly _tag: "error"; readonly error: Error }
* | { readonly _tag: "cancel" }
*
* const match = Match.type , f: Fn]
) => (
self: Matcher
) => Matcher<
I,
Types.AddWithout >
) => (
self: Matcher
) => Matcher<
I,
Types.AddWithout ,
Pr,
Ret
> = internal.tags
/**
* Matches values based on their `_tag` field and requires handling of all
* possible cases.
*
* **Details**
*
* This function is designed for **discriminated unions** where every possible
* `_tag` value must have a corresponding handler. Unlike {@link tags}, this
* function ensures **exhaustiveness**, meaning all cases must be explicitly
* handled. If a `_tag` value is missing from the mapping, TypeScript will
* report an error.
*
* **Example** (Handling all tag cases)
*
* ```ts import.meta.vitest
* import { Match, pipe } from "effect"
*
* const match = pipe(
* Match.type<
* { _tag: "A"; a: string } | { _tag: "B"; b: number } | {
* _tag: "C"
* c: boolean
* }
* >(),
* Match.tagsExhaustive({
* A: (a) => a.a,
* B: (b) => b.b,
* C: (c) => c.c
* })
* )
* match({ _tag: "B", b: 42 }) // => 42
* ```
*
* @stability stable
* @category defining patterns
* @since 4.0.0
*/
export const tagsExhaustive: <
R,
Ret,
P extends
& TagHandlers<"_tag", R, Ret>
& { readonly [Tag in Exclude >
) => (
self: Matcher
) => [Pr] extends [never] ? (u: I) => Unify> : Unify> =
internal.tagsExhaustive
/**
* Creates a pattern that excludes a specific value while allowing all others.
*
* **When to use**
*
* Use to add a negative pattern case for inputs that should match when another
* pattern does not.
*
* **Details**
*
* Any excluded value bypasses the provided function and continues matching
* through later cases.
*
* **Example** (Ignoring a specific value)
*
* ```ts import.meta.vitest
* import { Match } from "effect"
*
* // Create a matcher for string or number values
* const match = Match.type :
P extends SafeRefinement