Match
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.
Completion
exhaustive
Signature
declare const exhaustive: <I, F, A, Pr, Ret>(
self: Matcher<I, F, never, A, Pr, Ret>,
) => [Pr] extends [never] ? (u: I) => Unify<A> : Unify<A>;Wraps the match result in an Option, representing an optional match.
When to use
Use to finalize a matcher when unmatched input is expected and should become Option.none.
Details
This function ensures that the result of a matcher is wrapped in an Option, making it easy to handle cases where no pattern matches. If a match is found, it returns Some(value), otherwise, it returns None.
This is useful in cases where a missing match is expected and should be handled explicitly rather than throwing an error or returning a default value.
See
Signature
declare const option: <I, F, R, A, Pr, Ret>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => [Pr] extends [never] ? (input: I) => Option.Option<Unify<A>> : Option.Option<Unify<A>>;Provides a fallback value when no patterns match.
When to use
Use to finalize a matcher with a fallback for unmatched input.
Details
This function ensures that a matcher always returns a valid result, even if no defined patterns match. It acts as a default case, similar to the default clause in a switch statement or the final else in an if-else chain.
See
optionfor finalizing unmatched input asOption.noneresultfor returning unmatched input as aResultfailureorElseAbsurdfor finalizing when unmatched input should be impossible
Signature
declare const orElse: <RA, Ret, F extends (_: RA) => Ret>(
f: F,
) => <I, R, A, Pr>(
self: Matcher<I, R, RA, A, Pr, Ret>,
) => [Pr] extends [never] ? (input: I) => Unify<ReturnType<F> | A> : Unify<ReturnType<F> | A>;orElseAbsurd
Returns a matcher that throws an error if no pattern matches.
When to use
Use to finalize a matcher when every remaining unmatched case should be impossible.
Details
This function finalizes a matcher by ensuring that if no patterns match, an error is thrown. It is useful when all cases should be covered, and any unexpected input should trigger an error instead of returning a default value.
When used, this function removes the need for an explicit fallback case and ensures that an unmatched value is never silently ignored.
See
exhaustivefor compile-time exhaustive matcher finalizationorElsefor providing a fallback for unmatched input
Signature
declare const orElseAbsurd: <I, R, RA, A, Pr, Ret>(
self: Matcher<I, R, RA, A, Pr, Ret>,
) => [Pr] extends [never] ? (input: I) => Unify<A> : Unify<A>;Wraps the match result in a Result, distinguishing matched and unmatched cases.
Details
This function ensures that the result of a matcher is always wrapped in an Result, allowing clear differentiation between successful matches (Ok(value)) and cases where no pattern matched (Err(unmatched value)).
This approach is particularly useful when handling optional values or when an unmatched case should be explicitly handled rather than returning a default value or throwing an error.
Signature
declare const result: <I, F, R, A, Pr, Ret>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => [Pr] extends [never] ? (input: I) => Result.Result<Unify<A>, R> : Result.Result<Unify<A>, R>;Constructors
Creates a matcher for a specific type.
When to use
Use to build a reusable matcher function for values of a known input type.
Details
This function defines a Matcher that operates on a given type, allowing you to specify conditions for handling different cases. Once the matcher is created, you can use pattern-matching functions like when to define how different values should be processed.
See
valuefor creating a matcher from a specific value.
Signature
declare const type: <I>() => Matcher<I, Types.Without<never>, I, never, never>;Creates a type-safe match function for discriminated unions based on _tag field.
Details
This function allows you to define exhaustive pattern matching for discriminated unions by providing handlers for each possible _tag value. It ensures type safety and can optionally enforce a specific return type across all branches.
Signature
declare const typeTags: {
<I, Ret>(): <
P extends {
[Tag in string]: (
_: Extract<
I,
{
readonly _tag: Tag;
}
>,
) => Ret;
} & { [Tag in string | number | symbol]: never },
>(
fields: P,
) => (input: I) => Ret;
<I>(): <
P extends {
[Tag in string]: (
_: Extract<
I,
{
readonly _tag: Tag;
}
>,
) => any;
} & { [Tag in string | number | symbol]: never },
>(
fields: P,
) => (input: I) => Unify<ReturnType<P[keyof P]>>;
};Creates a matcher from a specific value.
When to use
Use to match one concrete input immediately.
Details
This function allows you to define a Matcher directly from a given value, rather than from a type. This is useful when working with known values, enabling structured pattern matching on objects, primitives, or any data structure.
Once the matcher is created, you can use pattern-matching functions like when to define how different cases should be handled.
See
typefor creating a matcher from a specific type.
Signature
declare const value: <I>(i: I) => Matcher<I, Types.Without<never>, I, never, I>;Creates a match function for a specific value with discriminated union handling.
Details
This function provides a convenient way to pattern match on discriminated unions by providing an object that maps each _tag value to its corresponding handler. It's similar to a switch statement but with better type safety and exhaustiveness checking.
Signature
declare const valueTags: {
<
I,
P extends {
[Tag in string]: (
_: Extract<
I,
{
readonly _tag: Tag;
}
>,
) => any;
} & { [Tag in string | number | symbol]: never },
>(
fields: P,
): (input: I) => Unify<ReturnType<P[keyof P]>>;
<
I,
P extends {
[Tag in string]: (
_: Extract<
I,
{
readonly _tag: Tag;
}
>,
) => any;
} & { [Tag in string | number | symbol]: never },
>(
input: I,
fields: P,
): Unify<ReturnType<P[keyof P]>>;
};Defining Patterns
discriminator
Matches values based on a specified discriminant field.
When to use
Use to match one or more exact values of a discriminator field.
Details
This function is used to define pattern matching on objects that follow a discriminated union structure, where a specific field (e.g., type, kind, _tag) determines the variant of the object. It allows matching multiple values of the discriminant and provides a function to handle the matched cases.
See
discriminatorsfor defining several discriminator handlers at oncediscriminatorStartsWithfor matching string discriminator values by prefix
Signature
declare const discriminator: <D extends string>(
field: D,
) => <R, P extends Types.Tags<D, R> & string, Ret, Fn extends (_: Extract<R, Record<D, P>>) => Ret>(
...pattern: [first: P, values: Array<P>, f: Fn]
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Extract<R, Record<D, P>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, P>>>>,
A | ReturnType<Fn>,
Pr,
Ret
>;discriminators
Matches values based on a field that serves as a discriminator, mapping each possible value to a corresponding handler.
When to use
Use to define several discriminator handlers at once without finalizing the matcher.
Details
This function simplifies working with discriminated unions by letting you define a set of handlers for each possible value of a given field. Instead of chaining multiple calls to discriminator, this function allows defining all possible cases at once using an object where the keys are the possible values of the field, and the values are the corresponding handler functions.
See
discriminatorfor adding one discriminator case to a matcher pipelinediscriminatorsExhaustivefor handling every discriminator value and finalizing the matcher
Signature
declare const discriminators: <D extends string>(
field: D,
) => <
R,
Ret,
P extends { [Tag in Types.Tags<D, R> & string]: (_: Extract<R, Record<D, Tag>>) => Ret } & {
[Tag in Exclude<keyof P, Types.Tags<D, R>>]: never;
},
>(
fields: P,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Extract<R, Record<D, keyof P>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, keyof P>>>>,
A | ReturnType<P[keyof P] & {}>,
Pr,
Ret
>;discriminatorsExhaustive
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 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.
See
discriminatorsfor defining discriminator handlers without finalizing the matcher
Signature
declare const discriminatorsExhaustive: <D extends string>(
field: D,
) => <
R,
Ret,
P extends { [Tag in Types.Tags<D, R> & string]: (_: Extract<R, Record<D, Tag>>) => Ret } & {
[Tag in Exclude<keyof P, Types.Tags<D, R>>]: never;
},
>(
fields: P,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => [Pr] extends [never]
? (u: I) => Unify<A | ReturnType<P[keyof P]>>
: Unify<A | ReturnType<P[keyof P]>>;discriminatorStartsWith
Matches values where a specified field starts with a given prefix.
When to use
Use to match string discriminator values by prefix instead of exact value.
Details
Instead of checking for exact matches, this helper matches values that share a common prefix. For example, if the discriminant field contains hierarchical names like "A", "A.A", and "B", a single "A" rule can match both "A" and "A.A".
See
discriminatorfor matching exact discriminator values
Signature
declare const discriminatorStartsWith: <D extends string>(
field: D,
) => <R, P extends string, Ret, Fn extends (_: Extract<R, Record<D, `${P}${string}`>>) => Ret>(
pattern: P,
f: Fn,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Extract<R, Record<D, `${P}${string}`>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<D, `${P}${string}`>>>>,
A | ReturnType<Fn>,
Pr,
Ret
>;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.
See
whenfor adding a positive pattern case
Signature
declare const not: <
R,
P extends Types.PatternPrimitive<R> | Types.PatternBase<R>,
Ret,
Fn extends (_: Types.NotMatch<R, P>) => Ret,
>(
pattern: P,
f: Fn,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddOnly<F, Types.WhenMatch<R, P>>,
Types.ApplyFilters<I, Types.AddOnly<F, Types.WhenMatch<R, P>>>,
A | ReturnType<Fn>,
Pr,
Ret
>;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 discriminator for a different discriminator field.
Signature
declare const tag: <
R,
P extends Types.Tags<"_tag", R> & string,
Ret,
Fn extends (_: Extract<R, Record<"_tag", P>>) => Ret,
>(
...pattern: [first: P, values: Array<P>, f: Fn]
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Extract<R, Record<"_tag", P>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<"_tag", P>>>>,
ReturnType<Fn> | A,
Pr,
Ret
>;tagStartsWith
Matches values where the _tag field starts with a given prefix.
Details
This function allows you to match on values in a discriminated union based on whether the _tag field starts with a specified prefix. It is useful for handling hierarchical or namespaced tags, where multiple related cases share a common prefix.
Signature
declare const tagStartsWith: <
R,
P extends string,
Ret,
Fn extends (_: Extract<R, Record<"_tag", `${P}${string}`>>) => Ret,
>(
pattern: P,
f: Fn,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Extract<R, Record<"_tag", `${P}${string}`>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Extract<R, Record<"_tag", `${P}${string}`>>>>,
ReturnType<Fn> | A,
Pr,
Ret
>;Defines a condition for matching values.
When to use
Use to add one positive pattern case to a Match.type or Match.value pipeline when a direct value, predicate, or structured object pattern should run a handler for matching input.
Details
Supports both direct value comparisons and predicate functions. If the pattern matches, the associated function is executed and the matched input is removed from the remaining cases tracked by the matcher.
See
Signature
declare const when: <
R,
P extends Types.PatternPrimitive<R> | Types.PatternBase<R>,
Ret,
Fn extends (_: Types.WhenMatch<R, P>) => Ret,
>(
pattern: P,
f: Fn,
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Types.PForExclude<P>>,
Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<P>>>,
A | ReturnType<Fn>,
Pr,
Ret
>;Matches a value that satisfies all provided patterns.
Details
This function allows defining a condition where a value must match all the given patterns simultaneously. If the value satisfies every pattern, the associated function is executed.
Unlike when, which matches a single pattern at a time, this function ensures that multiple conditions are met before executing the callback. It is useful when checking for values that need to fulfill multiple criteria at once.
Signature
declare const whenAnd: <
R,
P extends ReadonlyArray<Types.PatternPrimitive<R> | Types.PatternBase<R>>,
Ret,
Fn extends (_: Types.WhenMatch<R, T.UnionToIntersection<P[number]>>) => Ret,
>(
...args: [patterns: P, f: Fn]
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Types.PForExclude<T.UnionToIntersection<P[number]>>>,
Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<T.UnionToIntersection<P[number]>>>>,
A | ReturnType<Fn>,
Pr
>;Matches one of multiple patterns in a single condition.
Details
This function allows defining a condition where a value matches any of the provided patterns. If a match is found, the associated function is executed. It simplifies cases where multiple patterns share the same handling logic.
Unlike when, which requires separate conditions for each pattern, this function enables combining them into a single statement, making the matcher more concise.
Signature
declare const whenOr: <
R,
P extends ReadonlyArray<Types.PatternPrimitive<R> | Types.PatternBase<R>>,
Ret,
Fn extends (_: Types.WhenMatch<R, P[number]>) => Ret,
>(
...args: [patterns: P, f: Fn]
) => <I, F, A, Pr>(
self: Matcher<I, F, R, A, Pr, Ret>,
) => Matcher<
I,
Types.AddWithout<F, Types.PForExclude<P[number]>>,
Types.ApplyFilters<I, Types.AddWithout<F, Types.PForExclude<P[number]>>>,
A | ReturnType<Fn>,
Pr,
Ret
>;Guards
Matches any value without restrictions.
When to use
Use to define an explicit catch-all pattern when the handler should receive the unmatched value.
Details
This predicate matches every input, including undefined, null, objects, primitives, and functions.
Gotchas
Match.any should usually be last because cases are checked in order and the first matching case wins.
See
Signature
declare const any: SafeRefinement<unknown, any>;Matches values of type bigint.
When to use
Use to match primitive bigint values.
Details
This predicate refines unknown values to bigints, allowing pattern matching on bigint types. BigInts are used for representing integers with arbitrary precision.
See
numberfor matching primitive number values
Signature
declare const bigint: Predicate.Refinement<unknown, bigint>;Matches values of type boolean.
When to use
Use to match primitive boolean values.
Details
This predicate refines unknown values to booleans, allowing pattern matching on boolean types. It only matches the primitive boolean values true and false.
See
isfor matching specific literal boolean values
Signature
declare const boolean: Predicate.Refinement<unknown, boolean>;Matches values that are instances of Date.
When to use
Use to match Date instances.
Details
This predicate refines unknown values to Date instances, allowing pattern matching on Date objects. It only matches actual Date instances, not date strings or timestamps.
See
instanceOffor matching instances of any constructor
Signature
declare const date: Predicate.Refinement<unknown, Date>;Matches any defined (non-null and non-undefined) value.
When to use
Use to exclude only null and undefined from a match branch.
Details
This predicate matches values that are neither null nor undefined, effectively filtering out nullish values while preserving all other types.
See
anyfor matching every value without excluding nullish inputs
Signature
declare const defined: <A>(u: A) => u is A & {};instanceOf
Matches instances of a given class.
When to use
Use to match values that are instances of a constructor with type-safe narrowing.
Details
This predicate checks if a value is an instance of the specified constructor, providing type-safe matching for class instances and built-in objects.
See
instanceOfUnsafefor constructor matching without the same type-safety guaranteerecordfor matching broad non-null, non-array objects
Signature
declare const instanceOf: <A extends (...args: any) => any>(
constructor: A,
) => SafeRefinement<InstanceType<A>, never>;instanceOfUnsafe
Checks whether a value is an instance of a constructor without type-safe narrowing.
When to use
Use when you need constructor matching to use the unsafe refinement type.
Details
This predicate checks if a value is an instance of the specified constructor but doesn't provide the same type safety guarantees as the regular instanceOf. Use this when you need more flexibility but understand the type safety implications.
See
instanceOffor type-safe constructor matching
Signature
declare const instanceOfUnsafe: <A extends (...args: any) => any>(
constructor: A,
) => SafeRefinement<InstanceType<A>, InstanceType<A>>;Matches a specific set of literal values (e.g., Match.is("a", 42, true)).
When to use
Use to match one of several literal primitive or null values.
Details
This function creates a predicate that matches any of the provided literal values. It's useful for matching against multiple specific values in a single pattern.
Signature
declare const is: <Literals extends ReadonlyArray<string | number | bigint | boolean | null>>(
...literals: Literals
) => SafeRefinement<Literals[number]>;nonEmptyString
Matches non-empty strings.
When to use
Use to match strings whose length is greater than zero.
Details
This predicate matches any string that contains at least one character, effectively filtering out empty strings ("").
See
stringfor matching any string
Signature
declare const nonEmptyString: SafeRefinement<string, never>;Matches values of type number.
When to use
Use to match primitive number values, including NaN and infinities.
Details
This predicate refines unknown values to numbers, allowing pattern matching on numeric types. It matches all number values including integers, floats, Infinity, -Infinity, and NaN.
See
bigintfor matching primitive bigint values
Signature
declare const number: Predicate.Refinement<unknown, number>;Matches non-null objects other than arrays.
When to use
Use to match broad non-null, non-array object values.
Details
This predicate uses Predicate.isObject: it returns true for values whose runtime type is "object", are not null, and are not arrays. It can match Date, RegExp, and class instances; use instanceOf or a more specific pattern when those cases need to be distinguished.
See
instanceOffor matching a specific constructor
Signature
declare const record: Predicate.Refinement<
unknown,
{
[x: string | number | symbol]: unknown;
}
>;Matches values of type string.
Details
This predicate refines unknown values to strings, allowing pattern matching on string types. It's commonly used in type-based matchers to handle string cases.
Signature
declare const string: Predicate.Refinement<unknown, string>;Matches values of type symbol.
Details
This predicate refines unknown values to symbols, allowing pattern matching on symbol types. Symbols are unique identifiers that are often used as object keys or for creating private properties.
Signature
declare const symbol: Predicate.Refinement<unknown, symbol>;Models
Represents a single pattern matching case.
When to use
Use as the common public type for code that needs to inspect, store, or pass either positive or negative pattern matching cases.
Details
A Case can be either a positive match (When) or a negative match (Not). Cases are the building blocks of pattern matching logic and determine how values are tested and transformed.
See
Signature
type Case = When | Not;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.
Signature
type Matcher<Input, Filters, RemainingApplied, Result, Provided, Return = any> =
| TypeMatcher<Input, Filters, RemainingApplied, Result, Return>
| ValueMatcher<Input, Filters, RemainingApplied, Result, Provided, Return>;Represents a negative pattern matching case.
Details
A Not case contains the logic to test if a value does NOT match a specific pattern and the function to evaluate when the pattern doesn't match. It's used for exclusion-based pattern matching.
Signature
interface Not {
readonly _tag: "Not";
evaluate(input: unknown): any;
guard(u: unknown): boolean;
}SafeRefinement interface
A safe refinement that narrows types without runtime errors.
Details
SafeRefinement provides a way to refine types in pattern matching while maintaining type safety. Unlike regular predicates, safe refinements can transform the matched value's type without throwing runtime errors.
Signature
interface SafeRefinement<in A, out R = A> {
readonly "~effect/match/Match/SafeRefinement": (a: A) => R;
}TypeMatcher interface
Represents a pattern matcher that operates on types rather than specific values.
Details
A TypeMatcher is created when using Match.type<T>() and allows you to define patterns that will be applied to values of the specified type. It maintains type-level information about the input type, applied filters, remaining cases, and expected results.
Signature
interface TypeMatcher<in Input, out Filters, out Remaining, out Result, out Return = any> extends Pipeable {
readonly _tag: "TypeMatcher";
readonly "~effect/match/Match/Matcher": {
readonly _filters: Covariant<Filters>;
readonly _input: Contravariant<Input>;
readonly _remaining: Covariant<Remaining>;
readonly _result: Covariant<Result>;
readonly _return: Covariant<Return>;
};
readonly cases: readonly Array<Case>;
add<I, R, RA, A>(_case: Case): TypeMatcher<I, R, RA, A>;
}ValueMatcher interface
Represents a pattern matcher that operates on a specific provided value.
Details
A ValueMatcher is created when using Match.value(someValue) and contains the actual value to be matched against. It tracks both the provided value and the result of applying patterns to determine matches.
Signature
interface ValueMatcher<
in Input,
Filters,
out Remaining,
out Result,
Provided,
out Return = any,
> extends Pipeable {
readonly _tag: "ValueMatcher";
readonly "~effect/match/Match/Matcher": {
readonly _filters: Covariant<Filters>;
readonly _input: Contravariant<Input>;
readonly _result: Covariant<Result>;
readonly _return: Covariant<Return>;
};
readonly provided: Provided;
readonly value: Result<Provided, Remaining>;
add<I, R, RA, A, Pr>(_case: Case): ValueMatcher<I, R, RA, A, Pr>;
}Represents a positive pattern matching case.
Details
A When case contains the logic to test if a value matches a specific pattern and the function to evaluate when the pattern matches. It's the primary building block for pattern matching conditions.
Signature
interface When {
readonly _tag: "When";
evaluate(input: unknown): any;
guard(u: unknown): boolean;
}Other
Signature
declare const null: Predicate.Refinement<unknown, null>A namespace containing utility types for Match operations.
Details
This namespace provides advanced type-level utilities used internally by the Match module to perform complex pattern matching, type narrowing, and filter application. These types enable the sophisticated type inference that makes pattern matching both type-safe and ergonomic.
Signature
declare const undefined: Predicate.Refinement<unknown, undefined>;Utility Types
withReturnType
Ensures that all branches of a matcher return a specific type.
Details
This function enforces a consistent return type across all pattern-matching branches. By specifying a return type, TypeScript will check that every matching condition produces a value of the expected type.
Important: This function must be the first step in the matcher pipeline. If used later, TypeScript will not enforce type consistency correctly.
Signature
declare const withReturnType: <Ret>() => <I, F, R, A, Pr, _>(
self: Matcher<I, F, R, A, Pr, _>,
) => [Ret] extends [[A] extends [never] ? any : A]
? Matcher<I, F, R, A, Pr, Ret>
: "withReturnType constraint does not extend Result type";
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.