or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdpattern-matching.mdpatterns.mdvalidation.md

patterns.mddocs/

0

# Pattern Library

1

2

Comprehensive pattern construction utilities including wildcards, type-specific patterns, and combinators for building complex matching logic.

3

4

## Capabilities

5

6

### Wildcard Patterns

7

8

Basic patterns that match entire categories of values.

9

10

```typescript { .api }

11

/**

12

* Wildcard pattern matching any value

13

*/

14

const any: AnyPattern;

15

16

/**

17

* Alias for any wildcard pattern

18

*/

19

const _: AnyPattern;

20

21

/**

22

* String wildcard with chainable methods

23

*/

24

const string: StringPattern;

25

26

/**

27

* Number wildcard with chainable methods

28

*/

29

const number: NumberPattern;

30

31

/**

32

* BigInt wildcard with chainable methods

33

*/

34

const bigint: BigIntPattern;

35

36

/**

37

* Boolean wildcard pattern

38

*/

39

const boolean: BooleanPattern;

40

41

/**

42

* Symbol wildcard pattern

43

*/

44

const symbol: SymbolPattern;

45

46

/**

47

* Matches null or undefined values

48

*/

49

const nullish: NullishPattern;

50

51

/**

52

* Matches any non-null, non-undefined value

53

*/

54

const nonNullable: NonNullablePattern;

55

56

/**

57

* Symbol used for the matcher protocol to create custom patterns

58

*/

59

const matcher: unique symbol;

60

```

61

62

**Usage Examples:**

63

64

```typescript

65

import { match, P } from "ts-pattern";

66

67

// Basic wildcards

68

const handleValue = match(input)

69

.with(P.string, (str) => `string: ${str}`)

70

.with(P.number, (num) => `number: ${num}`)

71

.with(P.boolean, (bool) => `boolean: ${bool}`)

72

.with(P.nullish, () => 'null or undefined')

73

.with(P._, () => 'something else');

74

```

75

76

### String Patterns

77

78

Patterns for matching strings with specific characteristics.

79

80

```typescript { .api }

81

interface StringChainable<pattern> extends Chainable<pattern> {

82

/**

83

* Matches strings starting with prefix

84

* @param prefix - Required string prefix

85

*/

86

startsWith(prefix: string): StringChainable<GuardP<any, `${string}${string}`>>;

87

88

/**

89

* Matches strings ending with suffix

90

* @param suffix - Required string suffix

91

*/

92

endsWith(suffix: string): StringChainable<GuardP<any, `${string}${string}`>>;

93

94

/**

95

* Matches strings with minimum length

96

* @param min - Minimum string length

97

*/

98

minLength(min: number): StringChainable<GuardP<any, string>>;

99

100

/**

101

* Matches strings with exact length

102

* @param len - Exact string length

103

*/

104

length(len: number): StringChainable<GuardP<any, string>>;

105

106

/**

107

* Matches strings with maximum length

108

* @param max - Maximum string length

109

*/

110

maxLength(max: number): StringChainable<GuardP<any, string>>;

111

112

/**

113

* Matches strings containing substring

114

* @param substring - Required substring

115

*/

116

includes(substring: string): StringChainable<GuardP<any, string>>;

117

118

/**

119

* Matches strings against regular expression

120

* @param expression - Regular expression pattern

121

*/

122

regex(expression: string | RegExp): StringChainable<GuardP<any, string>>;

123

}

124

```

125

126

**Usage Examples:**

127

128

```typescript

129

// String pattern chaining

130

const validateInput = match(userInput)

131

.with(P.string.startsWith('http').includes('://'), (url) => validateUrl(url))

132

.with(P.string.regex(/^\d{3}-\d{2}-\d{4}$/), (ssn) => validateSSN(ssn))

133

.with(P.string.minLength(8).maxLength(32), (password) => validatePassword(password))

134

.otherwise(() => 'invalid input');

135

```

136

137

### Number Patterns

138

139

Patterns for matching numbers with specific constraints.

140

141

```typescript { .api }

142

interface NumberChainable<pattern> extends Chainable<pattern> {

143

/**

144

* Matches numbers between min and max (inclusive)

145

* @param min - Minimum value (inclusive)

146

* @param max - Maximum value (inclusive)

147

*/

148

between(min: number, max: number): NumberChainable<GuardP<any, number>>;

149

150

/**

151

* Matches numbers less than max

152

* @param max - Maximum value (exclusive)

153

*/

154

lt(max: number): NumberChainable<GuardP<any, number>>;

155

156

/**

157

* Matches numbers greater than min

158

* @param min - Minimum value (exclusive)

159

*/

160

gt(min: number): NumberChainable<GuardP<any, number>>;

161

162

/**

163

* Matches numbers less than or equal to max

164

* @param max - Maximum value (inclusive)

165

*/

166

lte(max: number): NumberChainable<GuardP<any, number>>;

167

168

/**

169

* Matches numbers greater than or equal to min

170

* @param min - Minimum value (inclusive)

171

*/

172

gte(min: number): NumberChainable<GuardP<any, number>>;

173

174

/**

175

* Matches integer numbers only

176

*/

177

int(): NumberChainable<GuardP<any, number>>;

178

179

/**

180

* Matches finite numbers (excludes Infinity and -Infinity)

181

*/

182

finite(): NumberChainable<GuardP<any, number>>;

183

184

/**

185

* Matches positive numbers (> 0)

186

*/

187

positive(): NumberChainable<GuardP<any, number>>;

188

189

/**

190

* Matches negative numbers (< 0)

191

*/

192

negative(): NumberChainable<GuardP<any, number>>;

193

}

194

```

195

196

**Usage Examples:**

197

198

```typescript

199

// Number pattern chaining

200

const categorizeNumber = match(value)

201

.with(P.number.int().positive(), (n) => `positive integer: ${n}`)

202

.with(P.number.between(0, 100), (n) => `percentage: ${n}%`)

203

.with(P.number.finite().negative(), (n) => `negative: ${n}`)

204

.otherwise(() => 'other number');

205

```

206

207

### BigInt Patterns

208

209

Patterns for matching bigint values with constraints.

210

211

```typescript { .api }

212

interface BigIntChainable<pattern> extends Chainable<pattern> {

213

/**

214

* Matches bigints between min and max (inclusive)

215

*/

216

between(min: bigint, max: bigint): BigIntChainable<GuardP<any, bigint>>;

217

218

/**

219

* Matches bigints less than max

220

*/

221

lt(max: bigint): BigIntChainable<GuardP<any, bigint>>;

222

223

/**

224

* Matches bigints greater than min

225

*/

226

gt(min: bigint): BigIntChainable<GuardP<any, bigint>>;

227

228

/**

229

* Matches bigints less than or equal to max

230

*/

231

lte(max: bigint): BigIntChainable<GuardP<any, bigint>>;

232

233

/**

234

* Matches bigints greater than or equal to min

235

*/

236

gte(min: bigint): BigIntChainable<GuardP<any, bigint>>;

237

238

/**

239

* Matches positive bigints (> 0n)

240

*/

241

positive(): BigIntChainable<GuardP<any, bigint>>;

242

243

/**

244

* Matches negative bigints (< 0n)

245

*/

246

negative(): BigIntChainable<GuardP<any, bigint>>;

247

}

248

```

249

250

### Collection Patterns

251

252

Patterns for matching arrays, sets, and maps.

253

254

```typescript { .api }

255

/**

256

* Matches arrays with optional element pattern

257

* @param pattern - Pattern to match array elements against

258

* @returns Array pattern that can be chained

259

*/

260

function array<input, const pattern extends Pattern<UnwrapArray<input>>>(

261

pattern?: pattern

262

): ArrayChainable<ArrayP<input, pattern>>;

263

264

/**

265

* Matches sets with optional element pattern

266

* @param pattern - Pattern to match set elements against

267

* @returns Set pattern that can be chained

268

*/

269

function set<input, const pattern extends Pattern<UnwrapSet<input>>>(

270

pattern?: pattern

271

): Chainable<SetP<input, pattern>>;

272

273

/**

274

* Matches maps with optional key and value patterns

275

* @param keyPattern - Pattern to match map keys against

276

* @param valuePattern - Pattern to match map values against

277

* @returns Map pattern that can be chained

278

*/

279

function map<

280

input,

281

const keyPattern extends Pattern<UnwrapMapKey<input>>,

282

const valuePattern extends Pattern<UnwrapMapValue<input>>

283

>(

284

keyPattern?: keyPattern,

285

valuePattern?: valuePattern

286

): Chainable<MapP<input, keyPattern, valuePattern>>;

287

288

interface ArrayChainable<pattern> extends Chainable<pattern> {

289

/**

290

* Makes the array pattern optional

291

*/

292

optional(): ArrayChainable<OptionalP<any, pattern>>;

293

294

/**

295

* Selects the matched array elements

296

*/

297

select(key?: string): ArrayChainable<SelectP<string, any, pattern>>;

298

}

299

```

300

301

**Usage Examples:**

302

303

```typescript

304

// Collection patterns

305

const processData = match(input)

306

.with(P.array(P.string), (strings) => strings.join(','))

307

.with(P.array(P.number.positive()), (nums) => nums.reduce((a, b) => a + b))

308

.with(P.set(P.string.startsWith('user:')), (userIds) => loadUsers(userIds))

309

.with(P.map(P.string, P.number), (stringToNum) => Object.fromEntries(stringToNum))

310

.otherwise(() => 'unsupported data structure');

311

```

312

313

### Combinatorial Patterns

314

315

Patterns that combine multiple patterns using logical operations.

316

317

```typescript { .api }

318

/**

319

* Creates a pattern that matches if ALL patterns match (AND logic)

320

* @param patterns - Patterns that must all match

321

* @returns Intersection pattern

322

*/

323

function intersection<

324

input,

325

const patterns extends readonly [Pattern<input>, ...Pattern<input>[]]

326

>(...patterns: patterns): Chainable<AndP<input, patterns>>;

327

328

/**

329

* Creates a pattern that matches if ANY pattern matches (OR logic)

330

* @param patterns - Patterns where at least one must match

331

* @returns Union pattern

332

*/

333

function union<

334

input,

335

const patterns extends readonly [Pattern<input>, ...Pattern<input>[]]

336

>(...patterns: patterns): Chainable<OrP<input, patterns>>;

337

338

/**

339

* Creates a pattern that matches if the sub-pattern does NOT match

340

* @param pattern - Pattern to negate

341

* @returns Negation pattern

342

*/

343

function not<input, const pattern extends Pattern<input>>(

344

pattern: pattern

345

): Chainable<NotP<input, pattern>>;

346

```

347

348

**Usage Examples:**

349

350

```typescript

351

// Combinatorial patterns

352

const validateUser = match(user)

353

.with(

354

P.intersection(

355

{ age: P.number.gte(21) },

356

{ permissions: P.array(P.string.includes('admin')) },

357

{ active: true }

358

),

359

(u) => 'admin user'

360

)

361

.with(

362

P.union(

363

{ type: 'guest' },

364

{ type: 'trial', expiresAt: P.when(d => d > new Date()) }

365

),

366

(u) => 'temporary access'

367

)

368

.with(

369

P.not({ banned: true }),

370

(u) => 'regular user'

371

)

372

.otherwise(() => 'access denied');

373

```

374

375

### Conditional Patterns

376

377

Patterns that use predicates and guards for custom matching logic.

378

379

```typescript { .api }

380

/**

381

* Creates a pattern that matches based on predicate function

382

* @param predicate - Function that returns truthy value for match

383

* @returns Guard pattern with type narrowing

384

*/

385

function when<input, predicate extends (value: input) => unknown>(

386

predicate: predicate

387

): GuardP<

388

input,

389

predicate extends (value: any) => value is infer narrowed ? narrowed : never

390

>;

391

392

/**

393

* Creates a pattern that matches instances of a class

394

* @param classConstructor - Constructor function to match against

395

* @returns Instance pattern

396

*/

397

function instanceOf<T extends AnyConstructor>(

398

classConstructor: T

399

): Chainable<GuardP<unknown, InstanceType<T>>>;

400

401

/**

402

* Enables chainable methods on structural patterns

403

* @param pattern - Structural pattern to make chainable

404

* @returns Chainable pattern with structural matching

405

*/

406

function shape<input, const pattern extends Pattern<input>>(

407

pattern: pattern

408

): Chainable<GuardP<input, InvertPattern<pattern, input>>>;

409

```

410

411

**Usage Examples:**

412

413

```typescript

414

// Conditional patterns

415

const handleError = match(error)

416

.with(P.instanceOf(TypeError), (err) => handleTypeError(err))

417

.with(P.instanceOf(RangeError), (err) => handleRangeError(err))

418

.with(P.when(err => err.code === 'ENOENT'), (err) => handleFileNotFound(err))

419

.with(P.shape({ status: P.number.between(400, 499) }).select(), (err) => handleClientError(err))

420

.otherwise(err => handleGenericError(err));

421

```

422

423

### Optional and Selection Patterns

424

425

Patterns for handling optional values and capturing selections.

426

427

```typescript { .api }

428

/**

429

* Makes a pattern optional (matches undefined or the pattern)

430

* @param pattern - Pattern to make optional

431

* @returns Optional pattern

432

*/

433

function optional<input, const pattern extends Pattern<input>>(

434

pattern: pattern

435

): Chainable<OptionalP<input, pattern>, 'optional'>;

436

437

/**

438

* Captures the matched value for use in handler

439

* @param key - Optional key name for named selection

440

* @param pattern - Optional pattern to match before selection

441

* @returns Selection pattern

442

*/

443

function select(): Chainable<AnonymousSelectP, 'select' | 'or' | 'and'>;

444

function select<input, const pattern extends Pattern<input>>(

445

pattern: pattern

446

): Chainable<SelectP<symbols.anonymousSelectKey, input, pattern>, 'select' | 'or' | 'and'>;

447

function select<input, const pattern extends Pattern<input>>(

448

key: string,

449

pattern: pattern

450

): Chainable<SelectP<string, input, pattern>, 'select' | 'or' | 'and'>;

451

```

452

453

**Usage Examples:**

454

455

```typescript

456

// Optional and selection patterns

457

const processConfig = match(config)

458

.with(

459

{

460

host: P.string,

461

port: P.number.optional(),

462

credentials: P.select('creds', { username: P.string, password: P.string })

463

},

464

({ creds }) => connectWithCredentials(creds.username, creds.password)

465

)

466

.with(

467

{ host: P.string, apiKey: P.select() },

468

(apiKey) => connectWithApiKey(apiKey)

469

)

470

.otherwise(() => 'invalid configuration');

471

```

472

473

### Universal Chainable Methods

474

475

Methods available on most patterns for additional composition.

476

477

```typescript { .api }

478

interface Chainable<pattern, excluded = never> {

479

/**

480

* Makes the pattern optional (if not excluded)

481

*/

482

optional(): excluded extends 'optional' ? never : Chainable<OptionalP<any, pattern>>;

483

484

/**

485

* Creates intersection with another pattern (if not excluded)

486

*/

487

and<P2>(pattern: P2): excluded extends 'and' ? never : Chainable<AndP<any, [pattern, P2]>>;

488

489

/**

490

* Creates union with another pattern (if not excluded)

491

*/

492

or<P2>(pattern: P2): excluded extends 'or' ? never : Chainable<OrP<any, [pattern, P2]>>;

493

494

/**

495

* Captures matched value (if not excluded)

496

*/

497

select(key?: string): excluded extends 'select' ? never : Chainable<SelectP<string, any, pattern>>;

498

}

499

```