### Install TS-Pattern via bun Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Install the ts-pattern library using bun. This command adds the package as a dependency to your project. ```sh bun add ts-pattern ``` -------------------------------- ### Install TS-Pattern via pnpm Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Install the ts-pattern library using pnpm. This command adds the package as a dependency to your project. ```sh pnpm add ts-pattern ``` -------------------------------- ### Install TS-Pattern via yarn Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Install the ts-pattern library using yarn. This command adds the package as a dependency to your project. ```sh yarn add ts-pattern ``` -------------------------------- ### Install TS-Pattern via npm Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Install the ts-pattern library using npm. This is the standard way to add the package to your project for use in Node.js or browser environments. ```sh npm install ts-pattern ``` -------------------------------- ### Example: Create and Use a Type Guard Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Demonstrates creating a type guard with isMatching and using it to narrow down the type of an unknown data object. ```typescript import { isMatching, P } from 'ts-pattern'; const isBlogPost = isMatching({ type: 'post', title: P.string, description: P.string, }); const data: unknown = { type: 'post', title: 'Getting Started', description: 'A beginner guide' }; if (isBlogPost(data)) { // data is now typed as { type: 'post', title: string, description: string } console.log(data.title); // "Getting Started" } ``` -------------------------------- ### Install TS-Pattern via jsr Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Install the ts-pattern library using jsr (JavaScript Registry). This command adds the package to your project. ```sh npx jsr add @gabriel/ts-pattern ``` -------------------------------- ### Example: Direct Pattern Check Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Shows how to use isMatching with both a pattern and a value for an immediate check and type narrowing. ```typescript import { isMatching, P } from 'ts-pattern'; const data: unknown = { name: 'Alice', age: 30 }; if (isMatching({ name: P.string, age: P.number }, data)) { // data is now typed correctly console.log(data.name, data.age); } ``` -------------------------------- ### Pattern Usage Example Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/types.md Demonstrates how to define a pattern for an object with specific string and number properties using ts-pattern's wildcards. ```typescript import { P } from 'ts-pattern'; const userPattern: P.Pattern<{ name: string; age: number }> = { name: P.string, age: P.number.gte(0), }; ``` -------------------------------- ### Complete Application Example with ts-pattern Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/README.md Demonstrates a full application using ts-pattern for type-safe action handling and runtime user validation. It includes defining types, using `isMatching` for validation, and `match` for handling different action types. ```typescript import { match, P, isMatching } from 'ts-pattern'; // Define types type User = { id: number; name: string; role: 'admin' | 'user' }; type Action = | { type: 'login'; user: User } | { type: 'logout' } | { type: 'update'; user: Partial }; // Validate user schema const isValidUser = isMatching({ id: P.number.positive(), name: P.string.minLength(1), role: P.union('admin', 'user'), } as const); // Handle actions function handleAction(action: Action): string { return match(action) .with({ type: 'login', user: P.select() }, (user) => { if (!isValidUser(user)) throw new Error('Invalid user'); return `${user.name} logged in`; }) .with({ type: 'logout' }, () => 'User logged out') .with( { type: 'update', user: { role: 'admin' } }, (action) => `Updated user ${action.user.id}` ) .exhaustive(); } // Type-safe usage const result1 = handleAction({ type: 'login', user: { id: 1, name: 'Alice', role: 'admin' } }); const result2 = handleAction({ type: 'logout' }); const result3 = handleAction({ type: 'update', user: { role: 'user' } }); ``` -------------------------------- ### Initialize Pattern Matching with match() Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Start a pattern matching expression by calling the match function with the input value. This creates a Match object for subsequent method calls like .with(), .when(), .otherwise(), and .run(). ```typescript match(value); ``` -------------------------------- ### Example: String Predicate Validation Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Shows how to use string predicates like 'includes' within a pattern to validate string content. ```typescript import { isMatching, P } from 'ts-pattern'; const isEmailValid = isMatching({ email: P.string.includes('@'), }); const user = { email: 'user@example.com' }; if (isEmailValid(user)) { console.log('Valid email format'); } ``` -------------------------------- ### Example: Type-Safe Union Handling with ts-pattern Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md Demonstrates how ts-pattern ensures type safety when matching on union types. This example shows a Result type where both success and error cases must be handled. ```typescript import { match } from 'ts-pattern'; type Result = { ok: true; value: T } | { ok: false; error: string }; function processResult(result: Result): string { return match(result) .with({ ok: true }, (res) => `Success: ${res.value}`) .with({ ok: false }, (res) => `Error: ${res.error}`) .exhaustive(); } // βœ… Type-safe: must handle both cases // If you remove either pattern, TypeScript error ``` -------------------------------- ### Match String Start with P.string.startsWith Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Use P.string.startsWith(str) to match strings that begin with a specific prefix. This is a convenient way to handle string inputs with common beginnings. ```typescript const fn = (input: string) => match(input) .with(P.string.startsWith('TS'), () => 'πŸŽ‰') .otherwise(() => '❌'); console.log(fn('TS-Pattern')); // logs 'πŸŽ‰' ``` -------------------------------- ### Example: Complex Type Composition with Response Handling Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/types.md Demonstrates composing complex types and patterns to handle different response statuses (success and error) and inferring the resulting type. It uses `match` with custom patterns and `P.infer`. ```typescript import { match, P } from 'ts-pattern'; type Response = | { status: 'success'; data: T } | { status: 'error'; error: string }; type User = { id: number; name: string }; const userResponsePattern = { status: 'success' as const, data: { id: P.number, name: P.string, }, } satisfies P.Pattern>; type UserResponse = P.infer; const response: Response = { status: 'success', data: { id: 1, name: 'Alice' } }; const result = match(response) .with(userResponsePattern, (res) => res.data.name) .with({ status: 'error' }, (res) => res.error) .exhaustive(); ``` -------------------------------- ### Example: Array Pattern Validation Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Demonstrates validating an array to ensure it contains only numbers using P.array and P.number. ```typescript import { isMatching, P } from 'ts-pattern'; const isNumberArray = isMatching(P.array(P.number)); function processNumbers(data: unknown) { if (isNumberArray(data)) { // data is typed as number[] return data.reduce((sum, n) => sum + n, 0); } return null; } ``` -------------------------------- ### Exhaustive Match Example Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates compile-time exhaustiveness checking with `.exhaustive()`. The first example fails to compile because a case is missing, while the second succeeds after handling all possibilities. ```typescript type Permission = 'editor' | 'viewer'; type Plan = 'basic' | 'pro'; const fn = (org: Plan, user: Permission) => match([org, user]) .with(['basic', 'viewer'], () => {}) .with(['basic', 'editor'], () => {}) .with(['pro', 'viewer'], () => {}) // Fails with `NonExhaustiveError<['pro', 'editor']>` // because the `['pro', 'editor']` case isn't handled. .exhaustive(); const fn2 = (org: Plan, user: Permission) => match([org, user]) .with(['basic', 'viewer'], () => {}) .with(['basic', 'editor'], () => {}) .with(['pro', 'viewer'], () => {}) .with(['pro', 'editor'], () => {}) .exhaustive(); // Works! ``` -------------------------------- ### Example: Validating API Responses Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Illustrates using isMatching to validate the structure of an API response against a defined schema before using the data. ```typescript import { isMatching, P } from 'ts-pattern'; const userSchema = { id: P.number, name: P.string, email: P.string, age: P.optional(P.number), } as const; type User = P.infer; const isValidUser = isMatching(userSchema); async function fetchUser(id: number) { const response = await fetch(`/api/users/${id}`); const data: unknown = await response.json(); if (isValidUser(data)) { return data; // type: User } throw new Error('Invalid user data'); } ``` -------------------------------- ### Example: Inferring User Type Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/types.md Demonstrates how to infer a TypeScript type from a pattern object using `P.infer`. This is useful for ensuring type safety when working with structured data. ```typescript import { P } from 'ts-pattern'; const userPattern = { id: P.number, name: P.string, } as const; type User = P.infer; // type User = { id: number; name: string } ``` -------------------------------- ### Pattern Composition Examples Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Combine patterns using provided utility functions. Supports union, intersection, negation, custom predicates, value selection, and optional patterns. ```typescript P.union(p1, p2) // Either pattern P.intersection(p1, p2) // Both patterns P.not(pattern) // Opposite P.when(predicate) // Custom condition P.select() // Extract value P.optional(pattern) // Optional key ``` -------------------------------- ### Example: Filtering Arrays with Type Guards Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Shows how to use a type guard created by isMatching to filter an array of unknown types, narrowing down to a specific interface. ```typescript import { isMatching, P } from 'ts-pattern'; interface Post { id: number; title: string; published: boolean; } const isPublishedPost = isMatching({ published: true, title: P.string, id: P.number } as const); const posts: unknown[] = [ { id: 1, title: 'Published', published: true }, { id: 2, title: 'Draft', published: false }, { id: 3, title: 'Finished', published: true } ]; const published = posts.filter(isPublishedPost); // published is typed as the narrowed type ``` -------------------------------- ### Example: Number Range Validation Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Illustrates validating number properties against a range using 'gte' (greater than or equal to) predicate. ```typescript import { isMatching, P } from 'ts-pattern'; const isAdult = isMatching({ age: P.number.gte(18), }); const person = { age: 25, name: 'Bob' }; if (isAdult(person)) { console.log('Person is an adult'); } ``` -------------------------------- ### Example: Complex Pattern Validation with Union Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Demonstrates validating complex event data structures using a union of patterns with isMatching. ```typescript import { isMatching, P } from 'ts-pattern'; const eventPattern = P.union( { type: 'click', target: P.string, x: P.number, y: P.number }, { type: 'keydown', key: P.string, ctrlKey: P.boolean } ); type Event = P.infer; const isValidEvent = isMatching(eventPattern); function handleEvent(event: unknown): Event | null { return isValidEvent(event) ? event : null; } ``` -------------------------------- ### Advanced Array Pattern Matching Examples Source: https://github.com/gvergnaud/ts-pattern/blob/main/docs/roadmap.md Illustrates advanced array pattern matching with ts-pattern, including specific values, typed arrays, and combinations of array types. ```typescript match(xs) .with([P.any, ...P.array()], (xs: [unknown, ...unknown[]]) => []) .with([42, ...P.array(P.number), '!'], (xs: [42, ...number[], '!']) => []) .with( [...P.array(P.number), ...P.array(P.string)], (xs: [...number[], ...string[]]) => [] ) .otherwise(() => []); ``` -------------------------------- ### Example: NonExhaustiveError Display Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md Illustrates how NonExhaustiveError displays the unmatched input value in its message and provides direct access to the input via the 'input' property. ```typescript import { match, NonExhaustiveError } from 'ts-pattern'; try { match({ type: 'unknown', value: 42 }) .with({ type: 'known' }, () => 'matched') .exhaustive(); } catch (error) { if (error instanceof NonExhaustiveError) { console.error(error.message); // Output: Pattern matching error: no pattern matches value {"type":"unknown","value":42} console.error(error.input); // Output: { type: 'unknown', value: 42 } } } ``` -------------------------------- ### State Reducer with ts-pattern Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Implement a state reducer function using ts-pattern's `match` for complex conditional logic. This example demonstrates handling different state and event combinations to transition between application states. ```typescript import { match, P } from 'ts-pattern'; const reducer = (state: State, event: Event) => match([state, event]) .returnType() .with( [{ status: 'loading' }, { type: 'success' }], ([_, event]) => ({ status: 'success', data: event.data }) ) .with( [{ status: 'loading' }, { type: 'error', error: P.select() }], (error) => ({ status: 'error', error }) ) .with( [{ status: P.not('loading') }, { type: 'fetch' }], () => ({ status: 'loading', startTime: Date.now() }) ) .with( [ { status: 'loading', startTime: P.when((t) => t + 2000 < Date.now()), }, { type: 'cancel' }, ], () => ({ status: 'idle' }) ) .with(P._, () => state) .exhaustive(); ``` -------------------------------- ### Add Multiple Pattern Cases with .with() Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/match.md Chain multiple .with() calls to handle different patterns. The first matching case is executed. This example shows handling multiple string literals. ```typescript import { match } from 'ts-pattern'; type Status = 'pending' | 'loading' | 'done'; const getEmoji = (status: Status) => match(status) .with('pending', 'loading', () => '⏳') .with('done', () => 'βœ…') .exhaustive(); console.log(getEmoji('pending')); // "⏳" ``` -------------------------------- ### Multi-Stage Event Matching with ts-pattern Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md Handle different event types using `match` with nested patterns. This example shows matching on a 'custom' event type with a record of unknown properties. ```typescript import { match, P } from 'ts-pattern'; type Event = | { type: 'click'; target: string; x: number; y: number } | { type: 'key'; code: string } | { type: 'custom'; data: Record }; function handleEvent(event: Event): string { return match(event) .with({ type: 'click' }, (e) => `Clicked ${e.target}`) .with({ type: 'key' }, (e) => `Key ${e.code}`) .with({ type: 'custom', data: P.record(P.string) }, (e) => `Custom event with ${Object.keys(e.data).length} properties` ) .exhaustive(); } ``` -------------------------------- ### Handling NonExhaustiveError with Try-Catch Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md While not recommended for normal control flow, NonExhaustiveError can be caught at runtime using a try-catch block. This example demonstrates how to identify and log the error. ```typescript import { match } from 'ts-pattern'; try { const result = match(value) .with({ type: 'a' }, () => 'A') .exhaustive(); } catch (error) { if (error instanceof NonExhaustiveError) { console.error('Unmatched value:', error.input); } } ``` -------------------------------- ### Guard in Conditional Chains Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/is-matching.md Use multiple guards in a conditional chain to progressively narrow down the type and authorize actions. This example checks for a general user role before checking for an admin role. ```typescript import { isMatching, P } from 'ts-pattern'; const userGuard = isMatching({ id: P.number, name: P.string, role: P.union('admin', 'user'), }); const adminGuard = isMatching({ id: P.number, name: P.string, role: 'admin', }); function authorize(data: unknown) { if (!userGuard(data)) return 'Not a user'; if (adminGuard(data)) return 'Admin access'; return 'User access'; } ``` -------------------------------- ### Handling Multiple Patterns Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates how to use `.with()` to match against multiple patterns simultaneously, providing a concise way to handle similar cases. ```APIDOC ## Matching Several Patterns ### Description Allows passing several patterns to `.with()`. If one of these patterns matches the input, the handler function will be called. This is similar to how `switch` statements can handle multiple cases with the same code block. ### Example ```ts const sanitize = (name: string) => match(name) .with('text', 'span', 'p', () => 'text') .with('btn', 'button', () => 'button') .otherwise(() => name); sanitize('span'); // 'text' sanitize('p'); // 'text' sanitize('button'); // 'button' ``` This feature also works with more complex patterns than strings, and exhaustiveness checking is maintained. ``` -------------------------------- ### Match Creation Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md The `match` function initializes a pattern matching expression. It takes an input value and returns a `Match` object that can be chained with methods like `.with()`, `.when()`, `.otherwise()`, and `.run()`. ```APIDOC ## `match` Function ### Description Creates a `Match` object on which you can later call `.with`, `.when`, `.otherwise` and `.run`. ### Signature ```ts function match(input: TInput): Match; ``` ### Arguments #### `input` - **Required** - The input value your patterns will be tested against. ``` -------------------------------- ### match() Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/match.md Creates a pattern matching expression. It initializes a pattern matching builder and returns a Match object on which you can chain methods like `.with()`, `.when()`, or `.returnType()`, and finally execute with `.exhaustive()` or `.otherwise()`. ```APIDOC ## match() ### Description Creates a pattern matching expression. It initializes a pattern matching builder and returns a Match object on which you can chain methods like `.with()`, `.when()`, or `.returnType()`, and finally execute with `.exhaustive()` or `.otherwise()`. ### Parameters - **value** (input) - Required - The input value to match against patterns. ### Return Type `Match` β€” A Match builder object with chainable methods. ### Example ```typescript import { match, P } from 'ts-pattern'; type Result = { status: 'ok'; data: string } | { status: 'error'; error: Error }; const result: Result = { status: 'ok', data: 'Hello' }; const message = match(result) .with({ status: 'ok' }, (res) => `Success: ${res.data}`) .with({ status: 'error' }, (res) => `Error: ${res.error.message}`) .exhaustive(); console.log(message); // "Success: Hello" ``` ``` -------------------------------- ### Core Syntax for Pattern Matching Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/README.md Demonstrates the basic structure for using the match function with patterns and handlers. Ensure you import 'match' and 'P' from 'ts-pattern'. ```typescript import { match, P } from 'ts-pattern'; const result = match(input) .with(pattern1, handler1) .with(pattern2, handler2) .otherwise(defaultHandler); ``` -------------------------------- ### Match with Pattern and P Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates matching against string, number, and boolean types using both Pattern and P imports. Use this when you need to handle different primitive types based on their nature. ```typescript import { match, Pattern } from 'ts-pattern'; const toString = (value: unknown): string => match(value) .with(Pattern.string, (str) => str) .with(Pattern.number, (num) => num.toFixed(2)) .with(Pattern.boolean, (bool) => `${bool}`) .otherwise(() => 'Unknown'); ``` ```typescript import { match, P } from 'ts-pattern'; const toString = (value: unknown): string => match(value) .with(P.string, (str) => str) .with(P.number, (num) => num.toFixed(2)) .with(P.boolean, (bool) => `${bool}`) .otherwise(() => 'Unknown'); ``` -------------------------------- ### Match with P._ and P.any Wildcards Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Explains the usage of `P._` and `P.any` as wildcards that match any value. These are useful when the specific value doesn't matter, and you just need to capture or acknowledge its presence. ```typescript import { match, P } from 'ts-pattern'; const input = 'hello'; const output = match(input) .with(P._, () => 'It will always match') // OR .with(P.any, () => 'It will always match') .otherwise(() => 'This string will never be used'); console.log(output); // => 'It will always match' ``` -------------------------------- ### Handling Incomplete Pattern Matching on Unions Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md Demonstrates a common cause of NonExhaustiveError where a union type is not fully matched. This example shows an incomplete match. ```typescript type Status = 'loading' | 'success' | 'error'; match(status) .with('loading', () => '...') .with('success', () => '...') .exhaustive(); // Throws if status is 'error' β€” incomplete! ``` -------------------------------- ### String Pattern Methods Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Methods available on `P.string` and string patterns for matching strings based on various criteria like prefixes, suffixes, substrings, regex, and length. ```APIDOC ## String Pattern Methods ### Description Methods for creating and manipulating string patterns. ### Methods - `startsWith(str: string)`: Matches strings starting with prefix. - `endsWith(str: string)`: Matches strings ending with suffix. - `includes(str: string)`: Matches strings containing substring. - `regex(expr: RegExp | string)`: Matches strings matching regex. - `minLength(min: number)`: Matches strings with length β‰₯ min. - `maxLength(max: number)`: Matches strings with length ≀ max. - `length(len: number)`: Matches strings with exact length. - `optional()`: Makes pattern optional. - `and(pattern)`: Combines patterns (intersection). - `or(pattern)`: Alternatives (union). - `select(key?)`: Extracts value for handler. ``` -------------------------------- ### Recursive Array Reversal with P.array Source: https://github.com/gvergnaud/ts-pattern/blob/main/docs/roadmap.md Demonstrates recursive array reversal using P.array and pattern matching. Requires the `match` function and `P` object to be defined. ```typescript const reverse = (xs: T[]): T[] => { return match(xs) .with([P.any, ...P.array()], ([x, ...xs]) => [...reverse(xs), x]) .otherwise(() => []); }; ``` -------------------------------- ### Main Exports Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Provides access to the core pattern matching functionalities: `match()` for building expressions and `isMatching()` for type guards or value checks. It also exposes the `Pattern` namespace (aliased as `P`) for defining patterns and the `NonExhaustiveError` class. ```APIDOC ## Main Exports (from 'ts-pattern') ### Functions - **`match()`**: Creates a pattern matching expression builder. - **`isMatching()`**: Creates a type guard or checks value against pattern. ### Namespaces / Objects - **`Pattern` (aliased `P`)**: Contains patterns, wildcards, combinators, and utilities for defining matchable structures. ### Classes - **`NonExhaustiveError`**: Error thrown when a pattern match is not exhaustive. ``` -------------------------------- ### Initialize ts-pattern match Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Initiate the pattern matching process with `match`. This function takes the value to be matched and returns a builder object for defining matching cases. ```typescript match([state, event]) ``` -------------------------------- ### Fixing NonExhaustiveError by Adding Missing Patterns Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/errors.md The recommended way to handle NonExhaustiveError is to ensure all possible cases of a union type are matched. This example adds the missing 'error' case. ```typescript import { match } from 'ts-pattern'; type Status = 'loading' | 'success' | 'error'; const message = match(status) .with('loading', () => 'Loading...') .with('success', () => 'Done!') .with('error', () => 'Failed') .exhaustive(); ``` -------------------------------- ### Defining Match Cases with `.with()` Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md The `.with()` method allows you to define specific patterns to match against the input value. It can accept a single pattern or multiple patterns, followed by a handler function. It also supports optional guard functions for additional conditions. ```APIDOC ## `.with()` Method ### Description Defines a case for the pattern matching expression. It takes a pattern (or multiple patterns) and a handler function. An optional `when` predicate can be provided for additional filtering. ### Signature ```ts function with( pattern: Pattern, handler: (selections: Selections, value: TInput) => TOutput ): Match; // Overload for multiple patterns function with( pattern1: Pattern, ...patterns: Pattern[], // no selection object is provided when using multiple patterns handler: (value: TInput) => TOutput ): Match; // Overload for guard functions function with( pattern: Pattern, when: (value: TInput) => unknown, handler: ( selection: Selection, value: TInput ) => TOutput ): Match; ``` ### Arguments #### `pattern: Pattern` - **Required** - The pattern your input must match for the handler to be called. - If you provide several patterns before providing the `handler`, the `.with` clause will match if one of the patterns matches. #### `when: (value: TInput) => unknown` - Optional - Additional condition the input must satisfy for the handler to be called. - The input will match if your guard function returns a truthy value. #### `handler: (selections: Selections, value: TInput) => TOutput` - **Required** - Function called when the match conditions are satisfied. - All handlers on a single `match` case must return values of the same type, `TOutput`. - `selections` is an object of properties selected from the input with the [`select` function](#select-patterns). - `TInput` might be narrowed to a more precise type using the `pattern`. ``` -------------------------------- ### Match Builder Methods Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md These methods are used to construct and execute pattern matching expressions using the `match()` function. They allow defining cases with patterns, guards, specifying return types, and handling exhaustive or default scenarios. ```APIDOC ## Match Builder Methods ### Main API - **`match.with(pattern, handler)`**: Adds a pattern case with its corresponding handler. - **`match.with(...patterns, handler)`**: Adds a case that matches if any of the provided patterns match, executing the same handler. - **`match.with(pattern, guard, handler)`**: Adds a case that matches a pattern only if the provided guard function also returns true. - **`match.when(predicate, handler)`**: Adds a condition-based case that executes the handler if the predicate function returns true. - **`match.returnType()`**: Sets an explicit return type `T` for the match expression. - **`match.exhaustive(handler?)`**: Ensures all possible patterns are handled, optionally providing a handler for the exhaustive case. - **`match.otherwise(handler)`**: Provides a default fallback handler to be executed if no other patterns match. - **`match.run()`**: Executes the match expression. Use with caution as it's unsafe if not exhaustive. - **`match.narrow()`**: Narrows the input type based on the defined patterns. ``` -------------------------------- ### Execute Pattern Matching with .exhaustive() Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Use .exhaustive() to execute pattern matching and get the result. It also enforces exhaustiveness checking, ensuring all cases are handled. Note that this can increase compilation times. ```typescript .exhaustive(); ``` -------------------------------- ### Pattern Namespace (P) Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md The `P` namespace provides a rich set of tools for defining patterns, including wildcards, combinators for logical operations, guards for conditional matching, selections for extracting values, and utilities for collections and type inference. ```APIDOC ## Pattern Namespace (P) ### Wildcards - **`P._` / `P.any`**: Matches any value. - **`P.unknown`**: Matches unknown values. - **`P.string`**: Matches strings (supports string predicates). - **`P.number`**: Matches numbers (supports number predicates). - **`P.bigint`**: Matches bigints (supports bigint predicates). - **`P.boolean`**: Matches booleans. - **`P.symbol`**: Matches symbols. - **`P.nullish`**: Matches null or undefined. - **`P.nonNullable`**: Matches non-null/undefined values. ### Combinators - **`P.union(...patterns)`**: Matches if any of the provided patterns match. - **`P.intersection(...patterns)`**: Matches if all of the provided patterns match. - **`P.not(pattern)`**: Matches if the provided pattern does NOT match. ### Guards & Selections - **`P.when(predicate)`**: Matches if the predicate function returns true. - **`P.select(key?, pattern?)`**: Extracts value(s) for handler injection. - **`P.optional(pattern)`**: Matches undefined or a pattern match. - **`P.instanceOf(constructor)`**: Matches class instances. - **`P.shape(pattern)`**: Wraps a structural pattern for chaining. ### Collections - **`P.array(pattern?)`**: Matches arrays with an optional element pattern. - **`P.set(pattern?)`**: Matches Sets with an optional element pattern. - **`P.map(keyPattern, valuePattern)`**: Matches Maps with specified key and value patterns. - **`P.record(keyPattern?, valuePattern?)`**: Matches Records with optional key and value patterns. ### Type Utilities - **`P.infer`**: Infers the type from a pattern definition. - **`P.narrow`**: Narrows the input type to values compatible with the pattern. - **`P.Pattern`**: Represents the type of all patterns matching `T`. - **`P.matcher`**: Symbol for implementing the Matcher Protocol. - **`P.unstable_Fn`**: Function type for the matcher protocol. - **`P.unstable_Matchable`**: Custom interface for matchable objects. - **`P.unstable_Matcher`**: Custom interface for matcher implementations. ``` -------------------------------- ### Match.with() Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/match.md Adds a pattern matching case to the builder. Multiple `.with()` calls can be chained, and the first matching case wins. It supports single patterns, multiple patterns, and cases with guard functions. ```APIDOC ## Match.with() ### Description Adds a pattern matching case to the builder. Multiple `.with()` calls can be chained, and the first matching case wins. It supports single patterns, multiple patterns, and cases with guard functions. ### Parameters - **pattern** (Pattern) - Required - The pattern to match against the input. - **patterns** (Pattern[]) - Optional - Additional patterns (for multiple-pattern case). If provided, the handler matches if any pattern matches. - **when** ((value: TInput) => unknown) - Optional - Optional guard function. The handler only executes if this returns a truthy value. - **handler** (Function) - Required - Function called when pattern matches. Receives selections object and the input value. ### Return Type `Match` β€” The Match builder for chaining. ### Example: Single Pattern ```typescript import { match, P } from 'ts-pattern'; const input = { type: 'user', name: 'Alice', age: 30 }; const description = match(input) .with({ type: 'user' }, (user) => `User: ${user.name}`) .otherwise(() => 'Unknown type'); console.log(description); // "User: Alice" ``` ### Example: Multiple Patterns ```typescript import { match } from 'ts-pattern'; type Status = 'pending' | 'loading' | 'done'; const getEmoji = (status: Status) => match(status) .with('pending', 'loading', () => '⏳') .with('done', () => 'βœ…') .exhaustive(); console.log(getEmoji('pending')); // "⏳" ``` ### Example: With Guard Function ```typescript import { match } from 'ts-pattern'; const getPrice = (age: number) => match(age) .with( P.number, (n) => n < 18, () => '$5 (child discount)' ) .with(P.number, () => '$10 (regular price)') .exhaustive(); console.log(getPrice(15)); // "$5 (child discount)" ``` ### Example: With Selection ```typescript import { match, P } from 'ts-pattern'; type Post = { type: 'post'; author: string; title: string }; const postSummary = match({ type: 'post', author: 'Bob', title: 'Intro' }) .with( { type: 'post', author: P.select('author'), title: P.select('title') }, ({ author, title }) => `"${title}" by ${author}` ) .otherwise(() => 'Unknown'); console.log(postSummary); // "Intro" by Bob ``` ``` -------------------------------- ### String Pattern Methods Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Use these methods to create patterns that match strings based on prefixes, suffixes, substrings, regular expressions, length, or optionality. They can be chained with other patterns using `and()` or `or()`. ```typescript P.string.startsWith("prefix") P.string.endsWith("suffix") P.string.includes("substring") P.string.regex(/regex/) P.string.minLength(5) P.string.maxLength(10) P.string.length(7) P.string.optional() P.string.and(P.pattern) P.string.or(P.pattern) P.string.select() P.string.select("key") ``` -------------------------------- ### P.string Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/patterns.md `P.string` is a wildcard that matches any string value. It can be chained with string predicates like `.startsWith()`, `.endsWith()`, `.includes()`, `.regex()`, etc. ```APIDOC ## P.string ### Description `P.string` is a wildcard that matches any string value. It can be chained with string predicates like `.startsWith()`, `.endsWith()`, `.includes()`, `.regex()`, etc. ### Example ```typescript import { match, P } from 'ts-pattern'; const greeting = match('hello') .with(P.string, (str) => str.toUpperCase()) .exhaustive(); console.log(greeting); // "HELLO" ``` ### Chainable Methods - `.startsWith(str)` β€” Matches strings starting with a substring - `.endsWith(str)` β€” Matches strings ending with a substring - `.includes(str)` β€” Matches strings containing a substring - `.minLength(min)` β€” Matches strings with at least `min` characters - `.maxLength(max)` β€” Matches strings with at most `max` characters - `.length(len)` β€” Matches strings with exactly `len` characters - `.regex(expr)` β€” Matches strings matching a RegExp ``` -------------------------------- ### BigInt Pattern Methods Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Methods available on `P.bigint` and bigint patterns for matching bigints within ranges, specific conditions (positive, negative), and pattern combinations. ```APIDOC ## BigInt Pattern Methods ### Description Methods for creating and manipulating bigint patterns. ### Methods - `between(min, max)`: Matches bigints in range [min, max]. - `lt(max)`: Matches bigints < max. - `gt(min)`: Matches bigints > min. - `lte(max)`: Matches bigints ≀ max. - `gte(min)`: Matches bigints β‰₯ min. - `positive()`: Matches positive bigints (> 0n). - `negative()`: Matches negative bigints (< 0n). - `optional()`: Makes pattern optional. - `and(pattern)`: Combines patterns (intersection). - `or(pattern)`: Alternatives (union). - `select(key?)`: Extracts value for handler. ``` -------------------------------- ### Basic Match Usage Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Use the `match` function to create a pattern matching builder. Define patterns with `.with()` and provide a handler function. A fallback handler can be specified using `.otherwise()`. ```typescript match(value) .with(pattern, handler) .otherwise(fallback) ``` -------------------------------- ### P.string Wildcard with Predicates Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/patterns.md Use P.string to match any string value. It supports chainable predicates like .startsWith(), .includes(), and .regex() for more specific string matching. ```typescript import { match, P } from 'ts-pattern'; const greeting = match('hello') .with(P.string, (str) => str.toUpperCase()) .exhaustive(); console.log(greeting); // "HELLO" ``` -------------------------------- ### Basic Pattern Matching with TS-Pattern Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates how to use `match` and `P` from `ts-pattern` to perform exhaustive pattern matching on a discriminated union type. Ensure all possible cases are handled using `.exhaustive()` to leverage type safety. ```tsx import { match, P } from 'ts-pattern'; type Data = | { type: 'text'; content: string } | { type: 'img'; src: string }; type Result = | { type: 'ok'; data: Data } | { type: 'error'; error: Error }; const result: Result = ...; const html = match(result) .with({ type: 'error' }, () =>

Oups! An error occured

) .with({ type: 'ok', data: { type: 'text' } }, (res) =>

{res.data.content}

) .with({ type: 'ok', data: { type: 'img', src: P.select() } }, (src) => ) .exhaustive(); ``` -------------------------------- ### Match Record Entries with P.record Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/patterns.md Use P.record to match object entries based on key and value patterns. It can match all string keys with number values, or specific key-value pairs. ```typescript import { match, P } from 'ts-pattern'; const scores = { alice: 95, bob: 87, charlie: 92 }; const classification = match(scores) .with(P.record(P.string, P.number.gte(90)), () => 'All high scores') .with(P.record(P.string, P.number), () => 'Mixed scores') .exhaustive(); console.log(classification); // "Mixed scores" ``` -------------------------------- ### Match Patterns with .with(pattern, handler) Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Define a pattern to match against the input value and a handler function to execute when the pattern matches. The handler's parameter type is narrowed down based on the pattern. ```typescript .with( [{ status: 'loading' }, { type: 'success' }], ([state, event]) => ({ // `state` is inferred as { status: 'loading' } // `event` is inferred as { type: 'success', data: string } status: 'success', data: event.data, }) ) ``` -------------------------------- ### Match Record with String Keys and Number Values Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Use P.record(P.string, P.number) to match objects where all keys are strings and all values are numbers. This is useful for validating consistent data structures. ```typescript import { match, P } from 'ts-pattern'; type Input = Record; const input: Input = { alice: 100, bob: 85, charlie: 92, }; const output = match(input) .with(P.record(P.string, P.number), (scores) => `All user scores`) .with(P.record(P.string, P.string), (names) => `All user names`) .otherwise(() => ''); console.log(output); // => "All user scores" ``` -------------------------------- ### Match with P.string Wildcard Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates using `P.string` to specifically match any value of type string. This is helpful for type-specific matching when you don't need to match a literal string. ```typescript import { match, P } from 'ts-pattern'; const input = 'hello'; const output = match(input) .with('bonjour', () => 'Wonβ€˜t match') .with(P.string, () => 'it is a string!') .exhaustive(); console.log(output); // => 'it is a string!' ``` -------------------------------- ### Number Pattern Methods Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/API-SUMMARY.md Methods available on `P.number` and number patterns for matching numbers within ranges, specific conditions (integers, finite, positive, negative), and pattern combinations. ```APIDOC ## Number Pattern Methods ### Description Methods for creating and manipulating number patterns. ### Methods - `between(min, max)`: Matches numbers in range [min, max]. - `lt(max)`: Matches numbers < max. - `gt(min)`: Matches numbers > min. - `lte(max)`: Matches numbers ≀ max. - `gte(min)`: Matches numbers β‰₯ min. - `int()`: Matches integers. - `finite()`: Matches finite numbers. - `positive()`: Matches positive numbers (> 0). - `negative()`: Matches negative numbers (< 0). - `optional()`: Makes pattern optional. - `and(pattern)`: Combines patterns (intersection). - `or(pattern)`: Alternatives (union). - `select(key?)`: Extracts value for handler. ``` -------------------------------- ### Unsafe Matching with `.run()` Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Executes the pattern match and returns the result. Throws an error if no pattern matches. Use with caution as it does not perform compile-time exhaustiveness checks. ```APIDOC ## `.run()` ### Description Returns the result of the pattern-matching expression, or **throws** if no pattern matched the input. `.run()` is similar to `.exhaustive()`, but is **unsafe** because exhaustiveness is not checked at compile time, so you have no guarantees that all cases are indeed covered. Use at your own risks. ### Signature ```ts function run(): TOutput; ``` ``` -------------------------------- ### Match with Object Patterns Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Shows how to match against object shapes, ensuring all defined properties exist and match their respective sub-patterns. Use this for discriminated unions or objects with specific structures. ```typescript import { match } from 'ts-pattern'; type Input = | { type: 'user'; name: string } | { type: 'image'; src: string } | { type: 'video'; seconds: number }; let input: Input = { type: 'user', name: 'Gabriel' }; const output = match(input) .with({ type: 'image' }, () => 'image') .with({ type: 'video', seconds: 10 }, () => 'video of 10 seconds.') .with({ type: 'user' }, ({ name }) => `user of name: ${name}`) .otherwise(() => 'something else'); console.log(output); // => 'user of name: Gabriel' ``` -------------------------------- ### P._ (any) Wildcard Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/patterns.md Use P._ or P.any as a catch-all pattern to match any value. It's useful for ignoring parts of a structure or as a default case. ```typescript import { match, P } from 'ts-pattern'; const result = match({ a: 1, b: 2 }) .with({ a: P._ }, () => 'Has property a') .with(P._, () => 'Matches anything'); console.log(result); // "Has property a" ``` -------------------------------- ### P.nullish Source: https://github.com/gvergnaud/ts-pattern/blob/main/_autodocs/patterns.md `P.nullish` is a wildcard that matches both `null` and `undefined`. Use this when you want to treat nullish values as equivalent. ```APIDOC ## P.nullish ### Description `P.nullish` is a wildcard that matches both `null` and `undefined`. Use this when you want to treat nullish values as equivalent. ``` -------------------------------- ### Match with Tuple Patterns Source: https://github.com/gvergnaud/ts-pattern/blob/main/README.md Demonstrates matching against array structures with fixed lengths and types, similar to TypeScript tuples. This is useful for parsing structured array inputs like commands or coordinates. ```typescript import { match, P } from 'ts-pattern'; type Input = | [number, '+', number] | [number, '-', number] | [number, '*', number] | ['-', number]; const input = [3, '*', 4] as Input; const output = match(input) .with([P._, '+', P._], ([x, , y]) => x + y) .with([P._, '-', P._], ([x, , y]) => x - y) .with([P._, '*', P._], ([x, , y]) => x * y) .with(['-', P._], ([, x]) => -x) .exhaustive(); console.log(output); // => 12 ```