Last Updated: 3/18/2026
isMatching() Function
isMatching is a type guard function that checks if a value matches a given pattern. It’s useful for runtime validation and type narrowing outside of match expressions.
Signatures
Curried Form (Returns Type Guard)
function isMatching<P extends Pattern<any>>(
pattern: P
): (value: any) => value is InvertPattern<P>;Direct Form (Returns Boolean)
function isMatching<P extends Pattern<any>>(
pattern: P,
value: any
): value is InvertPattern<P>;Usage
Single Argument (Curried)
Creates a reusable type guard function:
import { isMatching, P } from 'ts-pattern';
const isBlogPost = isMatching({
type: 'blogpost',
title: P.string,
description: P.string,
});
if (isBlogPost(value)) {
// ✅ value: { type: 'blogpost', title: string, description: string }
console.log(value.title);
}Two Arguments (Direct)
Direct boolean check:
const blogPostPattern = {
type: 'blogpost',
title: P.string,
description: P.string,
} as const;
if (isMatching(blogPostPattern, value)) {
// ✅ value is narrowed to match the pattern
console.log(value.title);
}Examples
API Response Validation
const userPattern = {
id: P.number,
name: P.string,
email: P.string,
age: P.number.optional(),
} as const;
async function fetchUser(id: number) {
const response = await fetch(`/api/users/${id}`);
const data: unknown = await response.json();
if (isMatching(userPattern, data)) {
// ✅ data is now typed as User
return data;
}
throw new Error('Invalid user data');
}Array Filtering
const isValidPost = isMatching({
title: P.string.minLength(1),
content: P.string.minLength(10),
author: { name: P.string },
});
const posts: unknown[] = await fetchPosts();
// Filter and narrow type in one go
const validPosts = posts.filter(isValidPost);
// validPosts: Array<{ title: string, content: string, author: { name: string } }>Complex Validation
const isAdultUser = isMatching({
type: 'user',
age: P.number.gte(18),
verified: true,
});
function processUser(input: unknown) {
if (isAdultUser(input)) {
// input is narrowed to verified adult user
console.log(`Processing user: ${input.age} years old`);
}
}Union Type Narrowing
type Response =
| { status: 'success'; data: string }
| { status: 'error'; error: Error }
| { status: 'loading' };
const isSuccess = isMatching({ status: 'success' });
const isError = isMatching({ status: 'error' });
function handleResponse(response: Response) {
if (isSuccess(response)) {
// response: { status: 'success'; data: string }
return response.data;
}
if (isError(response)) {
// response: { status: 'error'; error: Error }
throw response.error;
}
// response: { status: 'loading' }
return 'Loading...';
}Type Inference
The as const assertion helps TypeScript infer the most precise types:
// Without 'as const'
const pattern1 = { type: 'user', role: P.string };
// Inferred as: { type: string, role: Pattern<string> }
// With 'as const'
const pattern2 = { type: 'user', role: P.string } as const;
// Inferred as: { type: 'user', role: Pattern<string> }Benefits
- Type-safe validation: Combines runtime checks with compile-time type narrowing
- Reusable: Create validators once, use them anywhere
- Composable: Use with array methods like
.filter(),.find(),.some() - Readable: Pattern syntax is more declarative than manual type guards