0
# Pattern Matching
1
2
Core pattern matching functionality for creating exhaustive conditional logic with type safety and smart type inference.
3
4
## Capabilities
5
6
### Match Expression
7
8
Creates a chainable pattern matching expression for handling complex conditional logic.
9
10
```typescript { .api }
11
/**
12
* Creates a pattern matching expression
13
* @param value - Input value to match against patterns
14
* @returns Match expression for chaining patterns
15
*/
16
function match<const input, output = unknown>(
17
value: input
18
): Match<input, output>;
19
```
20
21
**Usage Examples:**
22
23
```typescript
24
import { match, P } from "ts-pattern";
25
26
// Basic pattern matching
27
const result = match(value)
28
.with('hello', () => 'greeting')
29
.with('goodbye', () => 'farewell')
30
.otherwise(() => 'unknown');
31
32
// Object pattern matching
33
const response = match(apiResponse)
34
.with({ status: 'success', data: P.select() }, (data) => data)
35
.with({ status: 'error', message: P.select() }, (msg) => { throw new Error(msg) })
36
.exhaustive();
37
```
38
39
### Pattern Matching Methods
40
41
Methods available on the match expression for building pattern matching logic.
42
43
```typescript { .api }
44
interface Match<input, output> {
45
/**
46
* Match against a pattern with handler function
47
* @param pattern - Pattern to match against input
48
* @param handler - Function to execute on match
49
* @returns Updated match expression
50
*/
51
with<const pattern extends Pattern<input>>(
52
pattern: pattern,
53
handler: (selections: P.infer<pattern>, value: input) => output
54
): Match<input, output>;
55
56
/**
57
* Match against a pattern with guard condition and handler
58
* @param pattern - Pattern to match against input
59
* @param guard - Additional condition function
60
* @param handler - Function to execute on match
61
* @returns Updated match expression
62
*/
63
with<const pattern extends Pattern<input>>(
64
pattern: pattern,
65
guard: (value: input) => unknown,
66
handler: (selections: P.infer<pattern>, value: input) => output
67
): Match<input, output>;
68
69
/**
70
* Match against multiple patterns with single handler
71
* @param patterns - Multiple patterns followed by handler function
72
* @returns Updated match expression
73
*/
74
with<const patterns extends readonly Pattern<input>[]>(
75
...args: [...patterns, (selections: any, value: input) => output]
76
): Match<input, output>;
77
78
/**
79
* Match based on predicate function
80
* @param predicate - Function returning truthy value for match
81
* @param handler - Function to execute on match
82
* @returns Updated match expression
83
*/
84
when(
85
predicate: (value: input) => unknown,
86
handler: (value: input) => output
87
): Match<input, output>;
88
89
/**
90
* Provide default case and return result
91
* @param handler - Default handler function
92
* @returns Final result of pattern matching
93
*/
94
otherwise(handler: (value: input) => output): output;
95
96
/**
97
* Ensure exhaustive matching and return result
98
* @param unexpectedValueHandler - Optional error handler for unmatched cases
99
* @returns Final result of pattern matching
100
* @throws NonExhaustiveError if no patterns match
101
*/
102
exhaustive(unexpectedValueHandler?: (value: input) => never): output;
103
104
/**
105
* Alias for exhaustive()
106
* @returns Final result of pattern matching
107
*/
108
run(): output;
109
110
/**
111
* Type-level method for return type inference
112
* @returns Match expression for type inference
113
*/
114
returnType(): Match<input, output>;
115
116
/**
117
* Type-level method for input type narrowing
118
* @returns Match expression for type narrowing
119
*/
120
narrow(): Match<input, output>;
121
}
122
```
123
124
**Usage Examples:**
125
126
```typescript
127
// Multiple patterns with single handler
128
const category = match(statusCode)
129
.with(200, 201, 202, () => 'success')
130
.with(400, 401, 403, 404, () => 'client-error')
131
.with(500, 502, 503, () => 'server-error')
132
.otherwise(() => 'unknown');
133
134
// Guard conditions
135
const processUser = match(user)
136
.with(
137
{ type: 'admin' },
138
(u) => u.permissions.includes('delete'),
139
(u) => deleteUser(u)
140
)
141
.with({ type: 'user', active: true }, (u) => processActiveUser(u))
142
.otherwise(() => 'inactive or unauthorized');
143
144
// Predicate matching
145
const handleAge = match(person)
146
.when(p => p.age >= 18, (p) => 'adult: ' + p.name)
147
.when(p => p.age >= 13, (p) => 'teen: ' + p.name)
148
.otherwise(p => 'child: ' + p.name);
149
```
150
151
### Pattern Types
152
153
Core pattern types used in matching expressions.
154
155
```typescript { .api }
156
/**
157
* Base pattern type that can match values of type T
158
*/
159
type Pattern<T> =
160
| T
161
| Matcher<any, any, any, any, any>
162
| (T extends readonly (infer U)[] ? Pattern<U>[] : never)
163
| (T extends object ? { [K in keyof T]?: Pattern<T[K]> } : never);
164
165
/**
166
* Matcher protocol interface for custom patterns
167
*/
168
interface Matcher<
169
input,
170
pattern,
171
narrowedOrFn,
172
exclude = never,
173
matcherType = string
174
> {
175
[matcher](): {
176
match: (value: input) => { matched: boolean; selections?: Record<string, unknown> };
177
getSelectionKeys?: () => string[];
178
matcherType?: matcherType;
179
};
180
}
181
182
/**
183
* Symbol used for matcher protocol
184
*/
185
declare const matcher: unique symbol;
186
```
187
188
### Selection and Type Inference
189
190
Pattern matching supports value selection and provides smart type inference.
191
192
```typescript { .api }
193
/**
194
* Infer the type of value matched by a pattern
195
*/
196
type infer<pattern> = InvertPattern<NoInfer<pattern>, unknown>;
197
198
/**
199
* Narrow input type to pattern-compatible subset
200
*/
201
type narrow<input, pattern> = ExtractPreciseValue<
202
input,
203
InvertPattern<pattern, input>
204
>;
205
```
206
207
**Usage Examples:**
208
209
```typescript
210
// Type inference with selections
211
const extractData = match(response)
212
.with({ success: true, data: P.select() }, (data) => {
213
// data is properly typed based on the pattern
214
return data;
215
})
216
.with({ success: false, error: P.select() }, (error) => {
217
// error is properly typed
218
throw error;
219
})
220
.exhaustive();
221
222
// Named selections
223
const processEvent = match(event)
224
.with(
225
{ type: 'user', action: 'login', userId: P.select('id'), timestamp: P.select('time') },
226
({ id, time }) => logUserLogin(id, time)
227
)
228
.with(
229
{ type: 'system', level: 'error', message: P.select() },
230
(message) => handleSystemError(message)
231
)
232
.exhaustive();
233
```