Last Updated: 3/18/2026
Wildcards
Wildcards are patterns that match specific types or any value. They’re the building blocks of more complex patterns.
P._ (Match Anything)
The P._ wildcard matches any value. It’s useful as a catch-all pattern or when you don’t care about the specific value.
import { match, P } from 'ts-pattern';
const output = match(input)
.with(P._, () => 'Will always match')
.exhaustive();Alias: P.any can be used instead of P._
match(input)
.with(P.any, () => 'Same as P._')
.exhaustive();Using P._ in Nested Patterns
// Match any tuple with three elements
match([1, 2, 3])
.with([P._, P._, P._], () => 'A tuple of 3 elements')
.exhaustive();
// Match any object with a 'type' property
match(obj)
.with({ type: P._ }, (obj) => `type is ${obj.type}`)
.exhaustive();P.string
Matches any string value.
const output = match(input)
.with(P.string, (str) => `It's a string: ${str}`)
.with(P.number, (num) => `It's a number: ${num}`)
.exhaustive();Example: Type Narrowing
type Input = string | number | boolean;
const describe = (input: Input) =>
match(input)
.with(P.string, (s) => `String of length ${s.length}`)
.with(P.number, (n) => `Number: ${n.toFixed(2)}`)
.with(P.boolean, (b) => `Boolean: ${b}`)
.exhaustive();P.number
Matches any number value (including NaN).
match(input)
.with(P.number, (num) => `Number: ${num}`)
.otherwise(() => 'Not a number');Excluding NaN
If you want to match numbers but exclude NaN, combine with P.not:
match(input)
.with(P.number.finite(), (num) => `Valid number: ${num}`)
.with(NaN, () => 'Not a number')
.exhaustive();P.boolean
Matches any boolean value (true or false).
match(input)
.with(P.boolean, (bool) => `Boolean: ${bool}`)
.with(P.string, () => 'String')
.exhaustive();P.nullish
Matches null or undefined. Useful when you want to treat both as equivalent.
type Input = string | null | undefined;
match(input)
.with(P.string, (str) => `String: ${str}`)
.with(P.nullish, () => 'No value')
.exhaustive();P.nonNullable
Matches any value except null or undefined.
type Input = number | null | undefined;
match(input)
.with(P.nonNullable, (num) => `Number: ${num}`)
.otherwise(() => 'Null or undefined');P.bigint
Matches bigint values.
match(input)
.with(P.bigint, (big) => `BigInt: ${big}n`)
.with(P.number, (num) => `Number: ${num}`)
.exhaustive();P.symbol
Matches symbol values.
const mySymbol = Symbol('my-symbol');
match(input)
.with(P.symbol, (sym) => 'It is a symbol')
.otherwise(() => 'Not a symbol');Combining Wildcards
Wildcards can be combined in object and array patterns:
// Match objects with string name and any age
match(user)
.with({ name: P.string, age: P._ }, (user) =>
`${user.name} (age unknown)`
)
.exhaustive();
// Match arrays starting with a number
match(arr)
.with([P.number, ...P.array()], ([first]) =>
`First element is ${first}`
)
.exhaustive();Wildcard Summary
| Wildcard | Matches | Example |
|---|---|---|
P._ or P.any | Any value | match(x).with(P._, ...) |
P.string | Any string | P.string matches "hello" |
P.number | Any number | P.number matches 42 |
P.boolean | true or false | P.boolean matches true |
P.nullish | null or undefined | P.nullish matches null |
P.nonNullable | Everything except null/undefined | Inverse of P.nullish |
P.bigint | Any bigint | P.bigint matches 100n |
P.symbol | Any symbol | P.symbol matches Symbol() |