Last Updated: 3/6/2026
.narrow()
The .narrow() method deeply narrows the input type to exclude all values that have previously been handled.
Signature
function narrow(): Match<Narrowed<TInput>, TOutput>;Description
This is useful when you want to exclude cases from union types or nullable properties that are deeply nested.
Note that handled cases of top-level union types are excluded by default, without calling .narrow().
Example
import { match, P } from 'ts-pattern';
type Input = { color: 'red' | 'blue'; size: 'small' | 'large' };
declare const input: Input;
const result = match(input)
.with({ color: 'red', size: 'small' }, (x) => `Red small`)
.with({ color: 'blue', size: 'large' }, (x) => `Blue large`)
.narrow() // 👈 Narrow the remaining cases
.otherwise((narrowedInput) => {
// narrowedInput:
// | { color: 'red'; size: 'large' }
// | { color: 'blue'; size: 'small' }
return 'other combination';
});When to Use
Use .narrow() when:
- Complex union types: You want to handle specific combinations first
- Better type inference: You need precise types in
.otherwise() - Nested properties: Union types are in nested object properties
- Documentation: Make it explicit which cases remain
Without .narrow()
Without .narrow(), the input type in .otherwise() would still be the full Input type:
const result = match(input)
.with({ color: 'red', size: 'small' }, (x) => 'Red small')
.otherwise((input) => {
// input: { color: 'red' | 'blue'; size: 'small' | 'large' }
// Still includes the handled case!
});Multiple .narrow() Calls
You can call .narrow() multiple times to progressively refine the type:
match(input)
.with({ color: 'red' }, () => 'red')
.narrow()
.with({ size: 'small' }, () => 'small blue')
.narrow()
.otherwise((x) => {
// x: { color: 'blue'; size: 'large' }
});