Last Updated: 3/18/2026
.exhaustive() and .otherwise()
These methods execute your pattern matching expression and return the result. They differ in how they handle unmatched cases.
.exhaustive()
Executes the pattern matching expression with compile-time exhaustiveness checking. TypeScript will ensure all possible cases have been handled.
Signature
function exhaustive(): TOutput;
function exhaustive(handler: (unexpectedValue: unknown) => TOutput): TOutput;Basic Usage
type Permission = 'editor' | 'viewer';
type Plan = 'basic' | 'pro';
const fn = (org: Plan, user: Permission) =>
match([org, user])
.with(['basic', 'viewer'], () => 'basic-viewer')
.with(['basic', 'editor'], () => 'basic-editor')
.with(['pro', 'viewer'], () => 'pro-viewer')
.with(['pro', 'editor'], () => 'pro-editor')
.exhaustive(); // ✅ All cases handled!Missing Case Error
const fn = (org: Plan, user: Permission) =>
match([org, user])
.with(['basic', 'viewer'], () => {})
.with(['basic', 'editor'], () => {})
.with(['pro', 'viewer'], () => {})
// ❌ TypeScript Error: NonExhaustiveError<['pro', 'editor']>
// The ['pro', 'editor'] case isn't handled
.exhaustive();Custom Error Handler
You can provide a custom handler for unexpected values:
match(input)
.with(P.string, (str) => str.length)
.exhaustive((unexpected) => {
console.error(`Unexpected value: ${unexpected}`);
return 0;
});.otherwise()
Executes the pattern matching expression with a default handler for unmatched cases. No exhaustiveness checking is performed.
Signature
function otherwise(defaultHandler: (value: TInput) => TOutput): TOutput;Basic Usage
const output = match(input)
.with({ type: 'text' }, (x) => x.content)
.with({ type: 'img' }, (x) => x.src)
.otherwise(() => 'default value');Accessing Unmatched Value
The default handler receives the original input value:
const output = match(input)
.with({ type: 'text' }, (x) => x.content)
.otherwise((unmatchedInput) => {
console.log('Unhandled input:', unmatchedInput);
return 'fallback';
});Comparison
| Feature | .exhaustive() | .otherwise() |
|---|---|---|
| Exhaustiveness checking | ✅ Yes | ❌ No |
| Compilation time | Slightly longer | Faster |
| Default handler | Optional | Required |
| Type safety | Higher | Lower |
| Use case | When you want type safety | When you want convenience |
When to Use
Use .exhaustive() when:
- Working with union types where all cases should be handled
- You want compile-time guarantees that no case is forgotten
- Building critical logic where missing a case would be a bug
Use .otherwise() when:
- The input type is very broad (e.g.,
unknown,any) - You intentionally want a catch-all case
- Exhaustiveness checking is impractical
- You prefer shorter compilation times
Equivalence
.otherwise(handler) is equivalent to:
.with(P._, handler).exhaustive()