The exhaustive Pattern Matching library for TypeScript with smart type inference
npx @tessl/cli install tessl/npm-ts-pattern@5.8.0TS-Pattern is the exhaustive Pattern Matching library for TypeScript with smart type inference. It brings the power of pattern matching from functional programming languages to TypeScript, enabling you to write safer, more expressive conditional logic with compile-time exhaustiveness checking.
npm install ts-patternimport { match, P, isMatching, NonExhaustiveError } from "ts-pattern";For CommonJS:
const { match, P, isMatching, NonExhaustiveError } = require("ts-pattern");import { match, P } from "ts-pattern";
type Data =
| { type: 'text'; content: string }
| { type: 'img'; src: string };
type Result =
| { type: 'ok'; data: Data }
| { type: 'error'; error: Error };
const result: Result = { type: 'ok', data: { type: 'text', content: 'Hello' } };
const html = match(result)
.with({ type: 'error' }, () => 'Error occurred')
.with({ type: 'ok', data: { type: 'text' } }, (res) => res.data.content)
.with({ type: 'ok', data: { type: 'img', src: P.select() } }, (src) => `<img src="${src}" />`)
.exhaustive();TS-Pattern is built around several key components:
match(value) function creating chainable pattern matching expressionsisMatching function for type guards and runtime validationCore pattern matching functionality for creating exhaustive conditional logic with type safety. Ideal for handling union types, API responses, and complex state machines.
/**
* Creates a pattern matching expression
* @param value - Input value to match against patterns
* @returns Match expression for chaining patterns
*/
function match<const input, output = unknown>(
value: input
): Match<input, output>;
interface Match<input, output> {
/** Match against a pattern with handler function */
with<const pattern extends Pattern<input>>(
pattern: pattern,
handler: (selections: P.infer<pattern>, value: input) => output
): Match<input, output>;
/** Match against a pattern with guard and handler */
with<const pattern extends Pattern<input>>(
pattern: pattern,
guard: (value: input) => unknown,
handler: (selections: P.infer<pattern>, value: input) => output
): Match<input, output>;
/** Match against multiple patterns with single handler */
with<const patterns extends readonly Pattern<input>[]>(
...args: [...patterns, (selections: any, value: input) => output]
): Match<input, output>;
/** Match based on predicate function */
when(
predicate: (value: input) => unknown,
handler: (value: input) => output
): Match<input, output>;
/** Provide default case and return result */
otherwise(handler: (value: input) => output): output;
/** Ensure exhaustive matching and return result */
exhaustive(unexpectedValueHandler?: (value: input) => never): output;
}Comprehensive pattern construction utilities including wildcards, type-specific patterns, and combinators for building complex matching logic.
// Wildcard patterns
const any: AnyPattern;
const _: AnyPattern; // alias for any
const string: StringPattern;
const number: NumberPattern;
const bigint: BigIntPattern;
const boolean: BooleanPattern;
const symbol: SymbolPattern;
const nullish: NullishPattern;
const nonNullable: NonNullablePattern;
// Pattern constructor functions
function optional<input, const pattern extends Pattern<input>>(
pattern: pattern
): Chainable<OptionalP<input, pattern>>;
function array<input, const pattern extends Pattern<UnwrapArray<input>>>(
pattern?: pattern
): ArrayChainable<ArrayP<input, pattern>>;
function union<input, const patterns extends readonly Pattern<input>[]>(
...patterns: patterns
): Chainable<OrP<input, patterns>>;
function intersection<input, const patterns extends readonly Pattern<input>[]>(
...patterns: patterns
): Chainable<AndP<input, patterns>>;Runtime type validation and type guard generation using pattern matching. Perfect for validating API responses, user input, and unknown data structures.
/**
* Creates a type guard function from a pattern
* @param pattern - Pattern to match against
* @returns Type guard function
*/
function isMatching<const p extends Pattern<unknown>>(
pattern: p
): (value: unknown) => value is P.infer<p>;
/**
* Validates if a value matches a pattern
* @param pattern - Pattern to match against
* @param value - Value to validate
* @returns Boolean indicating if value matches pattern
*/
function isMatching<const T, const P extends Pattern<T>>(
pattern: P,
value: T
): value is T & P.infer<P>;/**
* Error thrown when no pattern matches in exhaustive matching
*/
class NonExhaustiveError extends Error {
constructor(input: unknown);
input: unknown;
}// Core pattern type
type Pattern<T> =
| T
| Matcher<any, any, any, any, any>
| (T extends readonly (infer U)[] ? Pattern<U>[] : never)
| (T extends object ? { [K in keyof T]?: Pattern<T[K]> } : never);
// Pattern inference
type infer<pattern> = InvertPattern<NoInfer<pattern>, unknown>;
// Pattern narrowing
type narrow<input, pattern> = ExtractPreciseValue<
input,
InvertPattern<pattern, input>
>;