• English
  • Pattern Matching

    When working with Result types that have union error types, pattern matching becomes essential for handling different error scenarios effectively. This guide demonstrates how to use pattern matching to handle multiple error types gracefully.

    Why Pattern Matching for Union Errors?

    When your Result can fail with multiple different error types, you need a systematic way to handle each error type appropriately. Pattern matching provides a clean, type-safe approach to handle all possible error cases.

    Tip

    For more details about @praha/error-factory, see the Custom Error page.

    import { 
    const ErrorFactory: {
        <Name extends string = string, Message extends string = string, Fields extends ErrorFields = ErrorFields>(props: {
            name?: Name;
            message: Message | ((fields: Fields) => Message);
            fields?: Fields;
        }): ErrorConstructor<Name, Message, Fields>;
        fields<Fields extends ErrorFields>(): Fields;
    }

    A factory function that creates a base class for custom error types.

    Extend the returned class to define a custom error with a consistent structure, reducing boilerplate and ensuring type safety across your application.

    @typeParamName - Inferred as a string literal type from props.name when provided, or defaults to string when name is omitted.@typeParamMessage - Inferred as a string literal type from props.message when it is a string, or defaults to string when message is a function.@typeParamFields - Inferred from props.fields (via ErrorFactory.fields). Defaults to the base ErrorFields constraint when fields is omitted.@paramprops - Configuration for the error class.@paramprops .name - The value set as the name property on both the class and each instance. When omitted, name is inferred as string and set to new.target.name at construction time, which resolves to the name of the concrete subclass. Note that omitting name disables type narrowing via the name property; use name explicitly or instanceof for narrowing.@paramprops .message - The error message. Can be a static string or a function that receives the custom fields and returns a string, enabling dynamic message generation.@paramprops .fields - A type-level placeholder that declares the additional fields the error instance will carry. Use ErrorFactory.fields to create this value. When omitted, no additional fields are added to the instance.@returnsAn abstract base class typed as ErrorConstructor that should be extended to produce a concrete custom error class.@example

    Basic usage

    class NotFoundError extends ErrorFactory({
    name: 'NotFoundError',
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name);    // "NotFoundError"
    console.error(error.message); // "Resource not found"
    @example

    Omitting name

    class NotFoundError extends ErrorFactory({
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name); // "NotFoundError" (resolved from new.target.name)
    @example

    With cause

    class DatabaseError extends ErrorFactory({
    name: 'DatabaseError',
    message: 'A database error occurred',
    }) {}
    
    const error = new DatabaseError({ cause: new Error('Connection failed') });
    console.error(error.cause); // Error: Connection failed
    @example

    With additional fields

    class QueryError extends ErrorFactory({
    name: 'QueryError',
    message: 'An error occurred while executing a query',
    fields: ErrorFactory.fields<{ query: string }>(),
    }) {}
    
    const error = new QueryError({ query: 'SELECT * FROM users' });
    console.error(error.query); // "SELECT * FROM users"
    @example

    Dynamic message

    class ValidationError extends ErrorFactory({
    name: 'ValidationError',
    message: ({ field }) => `Validation failed for field '${field}'`,
    fields: ErrorFactory.fields<{ field: string }>(),
    }) {}
    
    const error = new ValidationError({ field: 'email' });
    console.error(error.message); // "Validation failed for field 'email'"
    ErrorFactory
    } from '@praha/error-factory';
    import {
    import Result
    Result
    } from '@praha/byethrow';
    class
    class PostNotFoundError
    PostNotFoundError
    extends
    ErrorFactory<"PostNotFoundError", "The requested post was not found.", ErrorFields>(props: {
        name?: "PostNotFoundError" | undefined;
        message: "The requested post was not found." | ((fields: ErrorFields) => "The requested post was not found.");
        fields?: ErrorFields | undefined;
    }): (new (options?: ErrorOptions) => Error & Readonly<{
        name: "PostNotFoundError";
        message: "The requested post was not found.";
    }>) & {
        name: "PostNotFoundError";
    }

    A factory function that creates a base class for custom error types.

    Extend the returned class to define a custom error with a consistent structure, reducing boilerplate and ensuring type safety across your application.

    @typeParamName - Inferred as a string literal type from props.name when provided, or defaults to string when name is omitted.@typeParamMessage - Inferred as a string literal type from props.message when it is a string, or defaults to string when message is a function.@typeParamFields - Inferred from props.fields (via ErrorFactory.fields). Defaults to the base ErrorFields constraint when fields is omitted.@paramprops - Configuration for the error class.@paramprops .name - The value set as the name property on both the class and each instance. When omitted, name is inferred as string and set to new.target.name at construction time, which resolves to the name of the concrete subclass. Note that omitting name disables type narrowing via the name property; use name explicitly or instanceof for narrowing.@paramprops .message - The error message. Can be a static string or a function that receives the custom fields and returns a string, enabling dynamic message generation.@paramprops .fields - A type-level placeholder that declares the additional fields the error instance will carry. Use ErrorFactory.fields to create this value. When omitted, no additional fields are added to the instance.@returnsAn abstract base class typed as ErrorConstructor that should be extended to produce a concrete custom error class.@example

    Basic usage

    class NotFoundError extends ErrorFactory({
    name: 'NotFoundError',
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name);    // "NotFoundError"
    console.error(error.message); // "Resource not found"
    @example

    Omitting name

    class NotFoundError extends ErrorFactory({
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name); // "NotFoundError" (resolved from new.target.name)
    @example

    With cause

    class DatabaseError extends ErrorFactory({
    name: 'DatabaseError',
    message: 'A database error occurred',
    }) {}
    
    const error = new DatabaseError({ cause: new Error('Connection failed') });
    console.error(error.cause); // Error: Connection failed
    @example

    With additional fields

    class QueryError extends ErrorFactory({
    name: 'QueryError',
    message: 'An error occurred while executing a query',
    fields: ErrorFactory.fields<{ query: string }>(),
    }) {}
    
    const error = new QueryError({ query: 'SELECT * FROM users' });
    console.error(error.query); // "SELECT * FROM users"
    @example

    Dynamic message

    class ValidationError extends ErrorFactory({
    name: 'ValidationError',
    message: ({ field }) => `Validation failed for field '${field}'`,
    fields: ErrorFactory.fields<{ field: string }>(),
    }) {}
    
    const error = new ValidationError({ field: 'email' });
    console.error(error.message); // "Validation failed for field 'email'"
    ErrorFactory
    ({
    name?: "PostNotFoundError" | undefined
    name
    : 'PostNotFoundError',
    message: "The requested post was not found." | ((fields: ErrorFields) => "The requested post was not found.")
    message
    : 'The requested post was not found.',
    }) {} class
    class PostPermissionError
    PostPermissionError
    extends
    ErrorFactory<"PostPermissionError", "You do not have permission to perform this action.", ErrorFields>(props: {
        name?: "PostPermissionError" | undefined;
        message: "You do not have permission to perform this action." | ((fields: ErrorFields) => "You do not have permission to perform this action.");
        fields?: ErrorFields | undefined;
    }): (new (options?: ErrorOptions) => Error & Readonly<{
        name: "PostPermissionError";
        message: "You do not have permission to perform this action.";
    }>) & {
        name: "PostPermissionError";
    }

    A factory function that creates a base class for custom error types.

    Extend the returned class to define a custom error with a consistent structure, reducing boilerplate and ensuring type safety across your application.

    @typeParamName - Inferred as a string literal type from props.name when provided, or defaults to string when name is omitted.@typeParamMessage - Inferred as a string literal type from props.message when it is a string, or defaults to string when message is a function.@typeParamFields - Inferred from props.fields (via ErrorFactory.fields). Defaults to the base ErrorFields constraint when fields is omitted.@paramprops - Configuration for the error class.@paramprops .name - The value set as the name property on both the class and each instance. When omitted, name is inferred as string and set to new.target.name at construction time, which resolves to the name of the concrete subclass. Note that omitting name disables type narrowing via the name property; use name explicitly or instanceof for narrowing.@paramprops .message - The error message. Can be a static string or a function that receives the custom fields and returns a string, enabling dynamic message generation.@paramprops .fields - A type-level placeholder that declares the additional fields the error instance will carry. Use ErrorFactory.fields to create this value. When omitted, no additional fields are added to the instance.@returnsAn abstract base class typed as ErrorConstructor that should be extended to produce a concrete custom error class.@example

    Basic usage

    class NotFoundError extends ErrorFactory({
    name: 'NotFoundError',
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name);    // "NotFoundError"
    console.error(error.message); // "Resource not found"
    @example

    Omitting name

    class NotFoundError extends ErrorFactory({
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name); // "NotFoundError" (resolved from new.target.name)
    @example

    With cause

    class DatabaseError extends ErrorFactory({
    name: 'DatabaseError',
    message: 'A database error occurred',
    }) {}
    
    const error = new DatabaseError({ cause: new Error('Connection failed') });
    console.error(error.cause); // Error: Connection failed
    @example

    With additional fields

    class QueryError extends ErrorFactory({
    name: 'QueryError',
    message: 'An error occurred while executing a query',
    fields: ErrorFactory.fields<{ query: string }>(),
    }) {}
    
    const error = new QueryError({ query: 'SELECT * FROM users' });
    console.error(error.query); // "SELECT * FROM users"
    @example

    Dynamic message

    class ValidationError extends ErrorFactory({
    name: 'ValidationError',
    message: ({ field }) => `Validation failed for field '${field}'`,
    fields: ErrorFactory.fields<{ field: string }>(),
    }) {}
    
    const error = new ValidationError({ field: 'email' });
    console.error(error.message); // "Validation failed for field 'email'"
    ErrorFactory
    ({
    name?: "PostPermissionError" | undefined
    name
    : 'PostPermissionError',
    message: "You do not have permission to perform this action." | ((fields: ErrorFields) => "You do not have permission to perform this action.")
    message
    : 'You do not have permission to perform this action.',
    }) {} class
    class PostAlreadyDeletedError
    PostAlreadyDeletedError
    extends
    ErrorFactory<"PostAlreadyDeletedError", "This post has already been deleted.", ErrorFields>(props: {
        name?: "PostAlreadyDeletedError" | undefined;
        message: "This post has already been deleted." | ((fields: ErrorFields) => "This post has already been deleted.");
        fields?: ErrorFields | undefined;
    }): (new (options?: ErrorOptions) => Error & Readonly<{
        name: "PostAlreadyDeletedError";
        message: "This post has already been deleted.";
    }>) & {
        name: "PostAlreadyDeletedError";
    }

    A factory function that creates a base class for custom error types.

    Extend the returned class to define a custom error with a consistent structure, reducing boilerplate and ensuring type safety across your application.

    @typeParamName - Inferred as a string literal type from props.name when provided, or defaults to string when name is omitted.@typeParamMessage - Inferred as a string literal type from props.message when it is a string, or defaults to string when message is a function.@typeParamFields - Inferred from props.fields (via ErrorFactory.fields). Defaults to the base ErrorFields constraint when fields is omitted.@paramprops - Configuration for the error class.@paramprops .name - The value set as the name property on both the class and each instance. When omitted, name is inferred as string and set to new.target.name at construction time, which resolves to the name of the concrete subclass. Note that omitting name disables type narrowing via the name property; use name explicitly or instanceof for narrowing.@paramprops .message - The error message. Can be a static string or a function that receives the custom fields and returns a string, enabling dynamic message generation.@paramprops .fields - A type-level placeholder that declares the additional fields the error instance will carry. Use ErrorFactory.fields to create this value. When omitted, no additional fields are added to the instance.@returnsAn abstract base class typed as ErrorConstructor that should be extended to produce a concrete custom error class.@example

    Basic usage

    class NotFoundError extends ErrorFactory({
    name: 'NotFoundError',
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name);    // "NotFoundError"
    console.error(error.message); // "Resource not found"
    @example

    Omitting name

    class NotFoundError extends ErrorFactory({
    message: 'Resource not found',
    }) {}
    
    const error = new NotFoundError();
    console.error(error.name); // "NotFoundError" (resolved from new.target.name)
    @example

    With cause

    class DatabaseError extends ErrorFactory({
    name: 'DatabaseError',
    message: 'A database error occurred',
    }) {}
    
    const error = new DatabaseError({ cause: new Error('Connection failed') });
    console.error(error.cause); // Error: Connection failed
    @example

    With additional fields

    class QueryError extends ErrorFactory({
    name: 'QueryError',
    message: 'An error occurred while executing a query',
    fields: ErrorFactory.fields<{ query: string }>(),
    }) {}
    
    const error = new QueryError({ query: 'SELECT * FROM users' });
    console.error(error.query); // "SELECT * FROM users"
    @example

    Dynamic message

    class ValidationError extends ErrorFactory({
    name: 'ValidationError',
    message: ({ field }) => `Validation failed for field '${field}'`,
    fields: ErrorFactory.fields<{ field: string }>(),
    }) {}
    
    const error = new ValidationError({ field: 'email' });
    console.error(error.message); // "Validation failed for field 'email'"
    ErrorFactory
    ({
    name?: "PostAlreadyDeletedError" | undefined
    name
    : 'PostAlreadyDeletedError',
    message: "This post has already been deleted." | ((fields: ErrorFields) => "This post has already been deleted.")
    message
    : 'This post has already been deleted.',
    }) {} // Example of a post deletion function type
    type PostDeleteError = PostNotFoundError | PostPermissionError | PostAlreadyDeletedError
    PostDeleteError
    = (
    |
    class PostNotFoundError
    PostNotFoundError
    |
    class PostPermissionError
    PostPermissionError
    |
    class PostAlreadyDeletedError
    PostAlreadyDeletedError
    ); // Function that can return multiple error types const
    const deletePost: (postId: string) => Result.ResultAsync<void, PostDeleteError>
    deletePost
    = async (
    postId: string
    postId
    : string):
    import Result
    Result
    .
    type ResultAsync<T, E> = Promise<Result.Result<T, E>>

    An asynchronous variant of Result , wrapped in a Promise.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const fetchData = async (): Result.ResultAsync<string, Error> => {
      try {
        const data = await fetch('...');
        return { type: 'Success', value: await data.text() };
      } catch (err) {
        return { type: 'Failure', error: err as Error };
      }
    };
    @categoryCore Types
    ResultAsync
    <void,
    type PostDeleteError = PostNotFoundError | PostPermissionError | PostAlreadyDeletedError
    PostDeleteError
    > => {
    // Implementation that can return any of the error types }; // Handling the result with pattern matching await
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<void, PostDeleteError>, Result.ResultAsync<"Post deleted successfully!", PostDeleteError>, Result.ResultAsync<"Post deleted successfully!", PostDeleteError>>(a: Result.ResultAsync<void, PostDeleteError>, ab: (a: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<"Post deleted successfully!", PostDeleteError>, bc: (b: Result.ResultAsync<"Post deleted successfully!", PostDeleteError>) => Result.ResultAsync<...>) => Result.ResultAsync<...> (+25 overloads)
    pipe
    (
    const deletePost: (postId: string) => Result.ResultAsync<void, PostDeleteError>
    deletePost
    ('123'),
    import Result
    Result
    .
    const map: <Result.ResultAsync<void, PostDeleteError>, "Post deleted successfully!">(fn: (a: void) => "Post deleted successfully!") => (result: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<"Post deleted successfully!", PostDeleteError> (+1 overload)
    map
    (() => 'Post deleted successfully!'),
    import Result
    Result
    .
    const inspectError: <Result.ResultAsync<"Post deleted successfully!", PostDeleteError>, void>(fn: (a: PostDeleteError) => void) => (result: Result.ResultAsync<"Post deleted successfully!", PostDeleteError>) => Result.ResultAsync<"Post deleted successfully!", PostDeleteError> (+1 overload)
    inspectError
    ((
    error: PostDeleteError
    error
    ) => {
    // Pattern matching to handle different error types }), );

    We strongly recommend using the ts-pattern for pattern matching. It provides excellent TypeScript support and ensures exhaustive matching.

    Installation

    npm
    yarn
    pnpm
    bun
    deno
    npm install ts-pattern

    Pattern Matching with ts-pattern

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    function match<const input, output = typeof unset>(value: input): Match<input, output>

    match creates a pattern matching expression.

    • Use .with(pattern, handler) to pattern match on the input.
    • Use .exhaustive() or .otherwise(() => defaultValue) to end the expression and get the result.

    Read the documentation for match on GitHub

    @example

    declare let input: "A" | "B";

    return match(input) .with("A", () => "It's an A!") .with("B", () => "It's a B!") .exhaustive();

    match
    } from 'ts-pattern';
    await
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<void, PostDeleteError>, Result.ResultAsync<void, PostDeleteError>>(a: Result.ResultAsync<void, PostDeleteError>, ab: (a: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+25 overloads)
    pipe
    (
    function deletePost(postId: string): Result.ResultAsync<void, PostDeleteError>
    deletePost
    ('123'),
    import Result
    Result
    .
    const inspectError: <Result.ResultAsync<void, PostDeleteError>, void>(fn: (a: PostDeleteError) => void) => (result: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+1 overload)
    inspectError
    ((
    error: PostDeleteError
    error
    ) => {
    match<PostDeleteError, typeof unset>(value: PostDeleteError): Match<PostDeleteError, typeof unset>

    match creates a pattern matching expression.

    • Use .with(pattern, handler) to pattern match on the input.
    • Use .exhaustive() or .otherwise(() => defaultValue) to end the expression and get the result.

    Read the documentation for match on GitHub

    @example

    declare let input: "A" | "B";

    return match(input) .with("A", () => "It's an A!") .with("B", () => "It's a B!") .exhaustive();

    match
    (
    error: PostDeleteError
    error
    )
    .
    with<{
        readonly name: "PostNotFoundError";
    }, void, PostNotFoundError>(pattern: {
        readonly name: "PostNotFoundError";
    }, handler: (selections: PostNotFoundError, value: PostNotFoundError) => void): Match<PostPermissionError | PostAlreadyDeletedError, typeof unset, [{
        readonly name: "PostNotFoundError";
    }], void> (+3 overloads)

    .with(pattern, handler) Registers a pattern and an handler function that will be called if the pattern matches the input value.

    Read the documentation for .with() on GitHub

    with
    ({
    name: "PostNotFoundError"
    name
    : 'PostNotFoundError' }, () => {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('The requested post was not found.');
    }) .
    with<{
        readonly name: "PostPermissionError";
    }, void, PostPermissionError>(pattern: {
        readonly name: "PostPermissionError";
    }, handler: (selections: PostPermissionError, value: PostPermissionError) => void): Match<PostAlreadyDeletedError, typeof unset, [{
        readonly name: "PostNotFoundError";
    }, {
        readonly name: "PostPermissionError";
    }], void> (+3 overloads)

    .with(pattern, handler) Registers a pattern and an handler function that will be called if the pattern matches the input value.

    Read the documentation for .with() on GitHub

    with
    ({
    name: "PostPermissionError"
    name
    : 'PostPermissionError' }, () => {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('You do not have permission to perform this action.');
    }) .
    with<{
        readonly name: "PostAlreadyDeletedError";
    }, void, PostAlreadyDeletedError>(pattern: {
        readonly name: "PostAlreadyDeletedError";
    }, handler: (selections: PostAlreadyDeletedError, value: PostAlreadyDeletedError) => void): Match<never, typeof unset, [{
        readonly name: "PostNotFoundError";
    }, {
        readonly name: "PostPermissionError";
    }, {
        readonly name: "PostAlreadyDeletedError";
    }], void> (+3 overloads)

    .with(pattern, handler) Registers a pattern and an handler function that will be called if the pattern matches the input value.

    Read the documentation for .with() on GitHub

    with
    ({
    name: "PostAlreadyDeletedError"
    name
    : 'PostAlreadyDeletedError' }, () => {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('This post has already been deleted.');
    }) .
    exhaustive: () => void (+1 overload)

    .exhaustive() checks that all cases are handled, and returns the result value.

    If you get a NonExhaustiveError, it means that you aren't handling all cases. You should probably add another .with(...) clause to match the missing case and prevent runtime errors.

    Read the documentation for .exhaustive() on GitHub

    exhaustive
    (); // Ensures all cases are handled
    }), );

    Alternative: Native TypeScript Pattern Matching

    If you prefer not to use external libraries, you can implement pattern matching using TypeScript's built-in features:

    Using instanceof Checks

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    await
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<void, PostDeleteError>, Result.ResultAsync<void, PostDeleteError>>(a: Result.ResultAsync<void, PostDeleteError>, ab: (a: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+25 overloads)
    pipe
    (
    function deletePost(postId: string): Result.ResultAsync<void, PostDeleteError>
    deletePost
    ('123'),
    import Result
    Result
    .
    const inspectError: <Result.ResultAsync<void, PostDeleteError>, void>(fn: (a: PostDeleteError) => void) => (result: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+1 overload)
    inspectError
    ((
    error: PostDeleteError
    error
    ) => {
    if (
    error: PostDeleteError
    error
    instanceof
    class PostNotFoundError
    PostNotFoundError
    ) {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('The requested post was not found.');
    } if (
    error: PostDeleteError
    error
    instanceof
    class PostPermissionError
    PostPermissionError
    ) {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('You do not have permission to perform this action.');
    } if (
    error: PostDeleteError
    error
    instanceof
    class PostAlreadyDeletedError
    PostAlreadyDeletedError
    ) {
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('This post has already been deleted.');
    } }), );

    Using Discriminated Unions

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    await
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<void, PostDeleteError>, Result.ResultAsync<void, PostDeleteError>>(a: Result.ResultAsync<void, PostDeleteError>, ab: (a: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+25 overloads)
    pipe
    (
    function deletePost(postId: string): Result.ResultAsync<void, PostDeleteError>
    deletePost
    ('123'),
    import Result
    Result
    .
    const inspectError: <Result.ResultAsync<void, PostDeleteError>, void>(fn: (a: PostDeleteError) => void) => (result: Result.ResultAsync<void, PostDeleteError>) => Result.ResultAsync<void, PostDeleteError> (+1 overload)
    inspectError
    ((
    error: PostDeleteError
    error
    ) => {
    switch (
    error: PostDeleteError
    error
    .
    Error.name: "PostNotFoundError" | "PostPermissionError" | "PostAlreadyDeletedError"
    name
    ) {
    case 'PostNotFoundError':
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('The requested post was not found.');
    break; case 'PostPermissionError':
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('You do not have permission to perform this action.');
    break; case 'PostAlreadyDeletedError':
    var console: Console
    console
    .
    Console.error(...data: any[]): void

    The console.error() static method outputs a message to the console at the "error" log level. The message is only displayed to the user if the console is configured to display error output. In most cases, the log level is configured within the console UI. The message may be formatted as an error, with red colors and call stack information.

    MDN Reference

    error
    ('This post has already been deleted.');
    break; default: // This should never happen if all error types are covered const
    const _exhaustiveCheck: never
    _exhaustiveCheck
    : never =
    error: never
    error
    ;
    throw new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    (`Unhandled error type: ${
    var JSON: JSON

    An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.

    JSON
    .
    JSON.stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string (+1 overload)

    Converts a JavaScript value to a JavaScript Object Notation (JSON) string.

    @paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer A function that transforms the results.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found.
    stringify
    (
    const _exhaustiveCheck: never
    _exhaustiveCheck
    )}`);
    } }), );