Pattern Matching
Branching logic written as a chain of if/else or a switch statement is easy
to get wrong: a forgotten case silently falls through, and adding a new variant
to a union does not force you to update every place that inspects it. The
Match module turns branching into a small, ordered table of cases that is
checked by the compiler. As you add cases, TypeScript tracks which inputs are
still unmatched, so finishing a matcher with Match.exhaustive is only allowed
once every case has been handled. Add a new union member later and the matcher
stops compiling until you handle it.
Match is a plain, synchronous module — it does not run inside Effect. Reach
for it whenever you need to classify a value: dispatching on a discriminated
union, mapping a domain event to a message, or narrowing an unknown input.
import { Match } from "effect"
// A discriminated union: each member carries a "_tag" fieldtype Event = | { readonly _tag: "UserCreated"; readonly id: string } | { readonly _tag: "UserDeleted"; readonly id: string }
// Build a reusable matcher for Event valuesconst describe = Match.type<Event>().pipe( // One branch per tag Match.tag("UserCreated", (event) => `created ${event.id}`), Match.tag("UserDeleted", (event) => `deleted ${event.id}`), // Compiles only because every tag above is handled Match.exhaustive)
console.log(describe({ _tag: "UserCreated", id: "u1" }))// Output: "created u1"How it works
Section titled “How it works”A matcher is built in three stages:
- Start a matcher with
Match.type<T>()for a reusable function over a known type, orMatch.value(x)to classify one value immediately. - Add cases with combinators like
Match.when,Match.tag, andMatch.not. Cases are tested top to bottom, and the first one that matches wins. - Finish with
Match.exhaustive(require every case to be covered),Match.orElse(supply a fallback), orMatch.option/Match.result(return the outcome as anOptionorResultinstead of throwing on a miss).
In this section
Section titled “In this section”- Building matchers — the full toolkit:
Match.typevsMatch.value, predicates and object patterns withMatch.when, tag- and discriminator-based matching, and the finalizers that turn a matcher into a value or a function.