Skip to Content
Patterns GuideWildcards P P String P Number

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

WildcardMatchesExample
P._ or P.anyAny valuematch(x).with(P._, ...)
P.stringAny stringP.string matches "hello"
P.numberAny numberP.number matches 42
P.booleantrue or falseP.boolean matches true
P.nullishnull or undefinedP.nullish matches null
P.nonNullableEverything except null/undefinedInverse of P.nullish
P.bigintAny bigintP.bigint matches 100n
P.symbolAny symbolP.symbol matches Symbol()