<
R,
const 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 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.
Example (Matching all provided patterns)
import { Match } from "effect"
type User = { readonly age: number; readonly role: "admin" | "user" }
const checkUser = Match.type<User>().pipe(
Match.whenAnd(
{ age: (n) => n >= 18 },
{ role: "admin" },
() => "Admin access granted"
),
Match.orElse(() => "Access denied")
)
console.log(checkUser({ age: 20, role: "admin" }))
// Output: "Admin access granted"
console.log(checkUser({ age: 20, role: "user" }))
// Output: "Access denied"export const 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 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.
Example (Matching all provided patterns)
import { Match } from "effect"
type User = { readonly age: number; readonly role: "admin" | "user" }
const checkUser = Match.type<User>().pipe(
Match.whenAnd(
{ age: (n) => n >= 18 },
{ role: "admin" },
() => "Admin access granted"
),
Match.orElse(() => "Access denied")
)
console.log(checkUser({ age: 20, role: "admin" }))
// Output: "Admin access granted"
console.log(checkUser({ age: 20, role: "user" }))
// Output: "Access denied"
whenAnd: <
function (type parameter) R in <R, const 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>R,
const function (type parameter) P in <R, const 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>P extends interface ReadonlyArray<T>ReadonlyArray<Types.type Types.PatternPrimitive<A> = A | Types.PredicateA<A> | SafeRefinement<any, any>Defines primitive patterns that can match simple values.
Details
This type represents the building blocks of pattern matching: predicates,
literal values, and safe refinements. These are the atomic patterns that
can be composed into more complex matching logic.
PatternPrimitive<function (type parameter) R in <R, const 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>R> | Types.type Types.PatternBase<A> = A extends readonly (infer _T)[] ? readonly any[] | Types.PatternPrimitive<A> : A extends Record<string, any> ? Partial<{ [K in keyof A]: Types.PatternPrimitive<A[K] & {}> | Types.PatternBase<A[K] & {}>; }> : neverDefines the structure for complex object and array patterns.
Details
This type represents patterns that can match against complex data structures
like objects and arrays. It supports nested pattern matching and partial
object matching, enabling sophisticated pattern compositions.
Example (Describing complex object patterns)
import { Match } from "effect"
// PatternBase enables complex object patterns
type UserPattern = Match.Types.PatternBase<{
name: string
age: number
role: "admin" | "user"
}>
// Allows: { name?: string | Predicate, age?: number | Predicate, ... }
// Example usage:
Match.value({ name: "Alice", age: 30, role: "admin" as const }).pipe(
Match.when(
{ age: (n: number) => n >= 18, role: "admin" },
(user: { name: string; age: number; role: "admin" }) =>
`Admin: ${user.name}`
),
Match.orElse(() => "Not an adult admin")
)
PatternBase<function (type parameter) R in <R, const 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>R>>,
function (type parameter) Ret in <R, const 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>Ret,
function (type parameter) Fn in <R, const 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>Fn extends (_: Types.WhenMatch<
R,
T.UnionToIntersection<P[number]>
>
_: Types.type Types.WhenMatch<R, P> = [0] extends [1 & R] ? Types.ResolvePred<P, any> : P extends SafeRefinement<infer SP, never> ? SP : P extends Predicate.Refinement<infer _R, infer RP extends infer _R> ? [Extract<R, RP>] extends [infer X] ? [X] extends [never] ? RP : X : never : P extends Types.PredicateA<infer PP> ? PP : Types.ExtractMatch<R, P>Computes the matched type when a pattern P is applied to type R.
Details
This utility type determines what type a value will have after successfully
matching against a pattern. It handles refinements, predicates, and complex
object patterns to provide accurate type narrowing.
Example (Computing matched types)
import type { Match } from "effect"
// WhenMatch computes the narrowed type after pattern matching
type StringMatch = Match.Types.WhenMatch<string | number, typeof Match.string>
// Result: string
type ObjectMatch = Match.Types.WhenMatch<
{ type: "user"; name: string } | {
type: "admin"
permissions: Array<string>
},
{ type: "user" }
>
// Result: { type: "user"; name: string }
WhenMatch<function (type parameter) R in <R, const 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>R, import TT.type UnionToIntersection<T> = (
T extends any ? (x: T) => any : never
) extends (x: infer R) => any
? R
: never
Transforms a union type into an intersection type.
When to use
Use to combine all members of a union into a single type with all their
properties. This is useful in advanced generic code where you need to merge
union variants.
Details
- Uses distributive conditional types and contra-variant inference.
- If the union members are incompatible (e.g.
string | number), the
result is never.
Example (Converting a union to an intersection)
import type { Types } from "effect"
type Union = { a: string } | { b: number }
type Result = Types.UnionToIntersection<Union>
// { a: string } & { b: number }
UnionToIntersection<function (type parameter) P in <R, const 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>P[number]>>) => function (type parameter) Ret in <R, const 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>Ret
>(
...args: [...patterns: P, f: Fn](parameter) args: {
length: number;
toString: () => string;
toLocaleString: { (): string; (locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string };
pop: () => Fn | P[number] | undefined;
push: (...items: Array<Fn | P[number]>) => number;
concat: { (...items: Array<ConcatArray<Fn | P[number]>>): Array<Fn | P[number]>; (...items: Array<Fn | P[number] | ConcatArray<Fn | P[number]>>): Array<Fn | P[number]> };
join: (separator?: string) => string;
reverse: () => Array<Fn | P[number]>;
shift: () => Fn | P[number] | undefined;
slice: (start?: number, end?: number) => Array<Fn | P[number]>;
sort: (compareFn?: ((a: Fn | P[number], b: Fn | P[number]) => number) | undefined) => [...patterns: P, f: Fn];
splice: { (start: number, deleteCount?: number): Array<Fn | P[number]>; (start: number, deleteCount: number, ...items: Array<Fn | P[number]>): Array<Fn | P[number]> };
unshift: (...items: Array<Fn | P[number]>) => number;
indexOf: (searchElement: Fn | P[number], fromIndex?: number) => number;
lastIndexOf: (searchElement: Fn | P[number], fromIndex?: number) => number;
every: { (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => value is S, thisArg?: any): this is S[]; (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => unknown, thisArg?: any): boo…;
some: (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => unknown, thisArg?: any) => boolean;
forEach: (callbackfn: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => void, thisArg?: any) => void;
map: (callbackfn: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => U, thisArg?: any) => Array<U>;
filter: { (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => value is S, thisArg?: any): Array<S>; (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => unknown, thisArg?: any): Array<…;
reduce: { (callbackfn: (previousValue: Fn | P[number], currentValue: Fn | P[number], currentIndex: number, array: Array<Fn | P[number]>) => Fn | P[number]): Fn | P[number]; (callbackfn: (previousValue: Fn | P[number], currentValue: Fn | P[number],…;
reduceRight: { (callbackfn: (previousValue: Fn | P[number], currentValue: Fn | P[number], currentIndex: number, array: Array<Fn | P[number]>) => Fn | P[number]): Fn | P[number]; (callbackfn: (previousValue: Fn | P[number], currentValue: Fn | P[number],…;
find: { (predicate: (value: Fn | P[number], index: number, obj: Array<Fn | P[number]>) => value is S, thisArg?: any): S | undefined; (predicate: (value: Fn | P[number], index: number, obj: Array<Fn | P[number]>) => unknown, thisArg?: any): Fn | …;
findIndex: (predicate: (value: Fn | P[number], index: number, obj: Array<Fn | P[number]>) => unknown, thisArg?: any) => number;
fill: (value: Fn | P[number], start?: number, end?: number) => [...patterns: P, f: Fn];
copyWithin: (target: number, start: number, end?: number) => [...patterns: P, f: Fn];
entries: () => ArrayIterator<[number, Fn | P[number]]>;
keys: () => ArrayIterator<number>;
values: () => ArrayIterator<Fn | P[number]>;
includes: (searchElement: Fn | P[number], fromIndex?: number) => boolean;
flatMap: (callback: (this: This, value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => U | ReadonlyArray<U>, thisArg?: This | undefined) => Array<U>;
flat: (this: A, depth?: D | undefined) => Array<FlatArray<A, D>>;
at: (index: number) => Fn | P[number] | undefined;
findLast: { (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => value is S, thisArg?: any): S | undefined; (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => unknown, thisArg?: any): F…;
findLastIndex: (predicate: (value: Fn | P[number], index: number, array: Array<Fn | P[number]>) => unknown, thisArg?: any) => number;
toReversed: () => Array<Fn | P[number]>;
toSorted: (compareFn?: ((a: Fn | P[number], b: Fn | P[number]) => number) | undefined) => Array<Fn | P[number]>;
toSpliced: { (start: number, deleteCount: number, ...items: Array<Fn | P[number]>): Array<Fn | P[number]>; (start: number, deleteCount?: number): Array<Fn | P[number]> };
with: (index: number, value: Fn | P[number]) => Array<Fn | P[number]>;
}
args: [...patterns: function (type parameter) P in <R, const 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>P, Fnf: function (type parameter) Fn in <R, const 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>Fn]
) => <function (type parameter) I in <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>I, function (type parameter) F in <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>F, function (type parameter) A in <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>A, function (type parameter) Pr in <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>Pr>(
self: Matcher<I, F, R, 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>(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>I, function (type parameter) F in <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>F, function (type parameter) R in <R, const 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>R, function (type parameter) A in <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>A, function (type parameter) Pr in <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>Pr, function (type parameter) Ret in <R, const 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>Ret>
) => 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>(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>I,
Types.type Types.AddWithout<A, X> = [A] extends [Types.Without<infer WX>] ? Types.Without<X | WX> : [A] extends [Types.Only<infer OX>] ? Types.Only<Exclude<OX, X>> : neverAdds a type to the exclusion filter, expanding what should be filtered out.
Details
This utility type manages the accumulation of excluded types during
pattern matching. When multiple exclusions are applied, it combines
them into a single filter representation.
Example (Accumulating excluded types)
import { Match } from "effect"
// AddWithout is used when combining multiple exclusions:
Match.type<string | number | boolean | null>().pipe(
Match.not(Match.string, () => "not string"),
Match.not(Match.number, () => "not number"),
// Type system uses AddWithout to combine exclusions
Match.orElse(() => "was string or number")
)
AddWithout<function (type parameter) F in <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>F, Types.type Types.PForExclude<P> = [Types.SafeRefinementR<Types.ToSafeRefinement<P>>] extends [infer X] ? X : neverComputes the excluded type when a pattern P is used for exclusion.
Details
This utility type determines what should be excluded from a union type
when a pattern is used in filtering operations. It transforms patterns
into their exclusion-safe representations.
Example (Computing excluded patterns)
import type { Match } from "effect"
// PForExclude computes what to exclude from type operations
type ExcludeString = Match.Types.PForExclude<typeof Match.string>
// Used internally to filter out string types
type ExcludeObject = Match.Types.PForExclude<{ type: "admin" }>
// Used internally to filter out admin objects
PForExclude<import TT.type UnionToIntersection<T> = (
T extends any ? (x: T) => any : never
) extends (x: infer R) => any
? R
: never
Transforms a union type into an intersection type.
When to use
Use to combine all members of a union into a single type with all their
properties. This is useful in advanced generic code where you need to merge
union variants.
Details
- Uses distributive conditional types and contra-variant inference.
- If the union members are incompatible (e.g.
string | number), the
result is never.
Example (Converting a union to an intersection)
import type { Types } from "effect"
type Union = { a: string } | { b: number }
type Result = Types.UnionToIntersection<Union>
// { a: string } & { b: number }
UnionToIntersection<function (type parameter) P in <R, const 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>P[number]>>>,
Types.type Types.ApplyFilters<I, A> = A extends Types.Only<infer X> ? X : A extends Types.Without<infer X> ? Exclude<I, X> : neverApplies accumulated filters to an input type, producing the final narrowed type.
Details
This utility type takes the collected inclusion/exclusion filters and
applies them to the input type to compute the final narrowed result.
It's the culmination of the type-level filtering process.
Example (Applying accumulated filters)
import type { Match } from "effect"
// ApplyFilters computes the final narrowed type:
type Result = Match.Types.ApplyFilters<
string | number | boolean,
Match.Types.Only<string>
>
// Result: string
type ExclusionResult = Match.Types.ApplyFilters<
string | number | boolean,
Match.Types.Without<string>
>
// Result: number | boolean
ApplyFilters<function (type parameter) I in <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>I, Types.type Types.AddWithout<A, X> = [A] extends [Types.Without<infer WX>] ? Types.Without<X | WX> : [A] extends [Types.Only<infer OX>] ? Types.Only<Exclude<OX, X>> : neverAdds a type to the exclusion filter, expanding what should be filtered out.
Details
This utility type manages the accumulation of excluded types during
pattern matching. When multiple exclusions are applied, it combines
them into a single filter representation.
Example (Accumulating excluded types)
import { Match } from "effect"
// AddWithout is used when combining multiple exclusions:
Match.type<string | number | boolean | null>().pipe(
Match.not(Match.string, () => "not string"),
Match.not(Match.number, () => "not number"),
// Type system uses AddWithout to combine exclusions
Match.orElse(() => "was string or number")
)
AddWithout<function (type parameter) F in <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>F, Types.type Types.PForExclude<P> = [Types.SafeRefinementR<Types.ToSafeRefinement<P>>] extends [infer X] ? X : neverComputes the excluded type when a pattern P is used for exclusion.
Details
This utility type determines what should be excluded from a union type
when a pattern is used in filtering operations. It transforms patterns
into their exclusion-safe representations.
Example (Computing excluded patterns)
import type { Match } from "effect"
// PForExclude computes what to exclude from type operations
type ExcludeString = Match.Types.PForExclude<typeof Match.string>
// Used internally to filter out string types
type ExcludeObject = Match.Types.PForExclude<{ type: "admin" }>
// Used internally to filter out admin objects
PForExclude<import TT.type UnionToIntersection<T> = (
T extends any ? (x: T) => any : never
) extends (x: infer R) => any
? R
: never
Transforms a union type into an intersection type.
When to use
Use to combine all members of a union into a single type with all their
properties. This is useful in advanced generic code where you need to merge
union variants.
Details
- Uses distributive conditional types and contra-variant inference.
- If the union members are incompatible (e.g.
string | number), the
result is never.
Example (Converting a union to an intersection)
import type { Types } from "effect"
type Union = { a: string } | { b: number }
type Result = Types.UnionToIntersection<Union>
// { a: string } & { b: number }
UnionToIntersection<function (type parameter) P in <R, const 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>P[number]>>>>,
function (type parameter) A in <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>A | type ReturnType<
T extends (...args: any) => any
> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType<function (type parameter) Fn in <R, const 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>Fn>,
function (type parameter) Pr in <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>Pr
> = import internalinternal.const whenAnd: <
R,
P extends ReadonlyArray<
| Types.PatternPrimitive<R>
| Types.PatternBase<R>
>,
Ret,
Fn extends (
_: Types.WhenMatch<
R,
Types.ArrayToIntersection<P>
>
) => 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<
Types.ArrayToIntersection<P>
>
>,
Types.ApplyFilters<
I,
Types.AddWithout<
F,
Types.PForExclude<
Types.ArrayToIntersection<P>
>
>
>,
A | ReturnType<Fn>,
Pr
>
whenAnd