Skip to content

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" field
type Event =
| { readonly _tag: "UserCreated"; readonly id: string }
| { readonly _tag: "UserDeleted"; readonly id: string }
// Build a reusable matcher for Event values
const 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"

A matcher is built in three stages:

  1. Start a matcher with Match.type<T>() for a reusable function over a known type, or Match.value(x) to classify one value immediately.
  2. Add cases with combinators like Match.when, Match.tag, and Match.not. Cases are tested top to bottom, and the first one that matches wins.
  3. Finish with Match.exhaustive (require every case to be covered), Match.orElse (supply a fallback), or Match.option / Match.result (return the outcome as an Option or Result instead of throwing on a miss).
  • Building matchers — the full toolkit: Match.type vs Match.value, predicates and object patterns with Match.when, tag- and discriminator-based matching, and the finalizers that turn a matcher into a value or a function.