Last Updated: 3/6/2026
Literal Patterns
Literals are primitive JavaScript values that can be used directly as patterns.
Supported Literals
Numbers
import { match } from 'ts-pattern';
const result = match(input)
.with(0, () => 'zero')
.with(1, () => 'one')
.with(42, () => 'the answer')
.with(3.14, () => 'pi')
.otherwise(() => 'other number');Strings
const result = match(input)
.with('hello', () => 'greeting')
.with('goodbye', () => 'farewell')
.with('', () => 'empty string')
.otherwise(() => 'other string');Booleans
const result = match(input)
.with(true, () => 'truthy')
.with(false, () => 'falsy')
.exhaustive();null and undefined
const result = match(input)
.with(null, () => 'null value')
.with(undefined, () => 'undefined value')
.otherwise(() => 'has a value');NaN
const result = match(input)
.with(NaN, () => 'not a number')
.with(P.number, (n) => `number: ${n}`)
.otherwise(() => 'other');BigInt
const result = match(input)
.with(0n, () => 'zero bigint')
.with(20n, () => 'twenty bigint')
.with(P.bigint, (n) => `bigint: ${n}`)
.otherwise(() => 'not a bigint');Symbols
const MY_SYMBOL = Symbol('my-symbol');
const result = match(input)
.with(MY_SYMBOL, () => 'found my symbol')
.with(P.symbol, () => 'some other symbol')
.otherwise(() => 'not a symbol');Complete Example
import { match, P } from 'ts-pattern';
const input: unknown = 2;
const output = match(input)
.with(2, () => 'number: two')
.with(true, () => 'boolean: true')
.with('hello', () => 'string: hello')
.with(undefined, () => 'undefined')
.with(null, () => 'null')
.with(NaN, () => 'number: NaN')
.with(20n, () => 'bigint: 20n')
.otherwise(() => 'something else');
console.log(output); // => 'number: two'Type Narrowing
When using literal patterns with union types, TypeScript will automatically narrow the type:
type Status = 'idle' | 'loading' | 'success' | 'error';
const getStatusMessage = (status: Status) =>
match(status)
.with('idle', (s) => {
// s is narrowed to 'idle'
return 'Ready to start';
})
.with('loading', (s) => {
// s is narrowed to 'loading'
return 'Please wait...';
})
.with('success', 'error', (s) => {
// s is narrowed to 'success' | 'error'
return s === 'success' ? 'Done!' : 'Failed!';
})
.exhaustive();Best Practices
- Use literals for exact matches: When you know the exact value you’re matching
- Combine with wildcards: Use literals for specific cases, wildcards for general ones
- Leverage type narrowing: Let TypeScript infer precise types from your patterns
- Group related literals: Use multiple patterns in a single
.with()for similar cases
// Good: Grouped related cases
match(httpStatus)
.with(200, 201, 204, () => 'Success')
.with(400, 401, 403, 404, () => 'Client Error')
.with(500, 502, 503, () => 'Server Error')
.otherwise(() => 'Unknown Status');