Skip to Content
Narrow

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:

  1. Complex union types: You want to handle specific combinations first
  2. Better type inference: You need precise types in .otherwise()
  3. Nested properties: Union types are in nested object properties
  4. 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' } });