• English
  • Custom Error

    When creating errors with Result.fail(), we strongly recommend using custom errors instead of plain strings or generic Error objects. This guide explains what custom errors are, why they're beneficial, and how to create them effectively.

    What are Custom Errors?

    Custom errors are specialized error classes that provide more structure and context than generic Error objects. They come in two main forms:

    Custom error classes inherit from the built-in Error class and provide additional functionality:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    import z
    z
    } from 'zod';
    class
    class ValidationError
    ValidationError
    extends
    var Error: ErrorConstructor
    Error
    {
    public override readonly
    ValidationError.name: "ValidationError"
    name
    = 'ValidationError';
    constructor(
    message: string
    message
    : string,
    options: ErrorOptions | undefined
    options
    ?: ErrorOptions) {
    super(
    message: string
    message
    ,
    options: ErrorOptions | undefined
    options
    );
    } } // Usage with Result.fail() const
    const validateEmail: (email: string) => Result.Result<string, ValidationError>
    validateEmail
    = (
    email: string
    email
    : string):
    import Result
    Result
    .
    type Result<T, E> = Result.Success<T> | Result.Failure<E>

    A union type representing either a success or a failure.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const doSomething = (): Result.Result<number, string> => {
      return Math.random() > 0.5
        ? { type: 'Success', value: 10 }
        : { type: 'Failure', error: 'Oops' };
    };
    @categoryCore Types
    Result
    <string,
    class ValidationError
    ValidationError
    > => {
    return
    import Result
    Result
    .
    const pipe: <string, Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, Result.Result<string, ValidationError>>(a: string, ab: (a: string) => Result.Result<string, readonly StandardSchemaV1.Issue[]>, bc: (b: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, ValidationError>) => Result.Result<string, ValidationError> (+25 overloads)
    pipe
    (
    email: string
    email
    ,
    import Result
    Result
    .
    const parse: <z.ZodString>(schema: z.ZodString) => (value: unknown) => Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]> (+1 overload)
    parse
    (
    import z
    z
    .
    function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)
    string
    ().
    ZodString.email(params?: string | z.core.$ZodCheckEmailParams): z.ZodString
    @deprecatedUse z.email() instead.
    email
    ()),
    import Result
    Result
    .
    const mapError: <Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, ValidationError>(fn: (a: readonly StandardSchemaV1.Issue[]) => ValidationError) => (result: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, ValidationError> (+1 overload)
    mapError
    ((
    error: readonly StandardSchemaV1.Issue[]
    error
    ) => new
    constructor ValidationError(message: string, options?: ErrorOptions): ValidationError
    ValidationError
    ('Invalid email format', {
    ErrorOptions.cause?: unknown
    cause
    :
    error: readonly StandardSchemaV1.Issue[]
    error
    })),
    ); };

    2. Objects with Identifiable Tags

    You can also use plain objects with distinguishable properties as error types:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    import z
    z
    } from 'zod';
    type
    type ValidationError = {
        type: "ValidationError";
        message: string;
        value: string;
    }
    ValidationError
    = {
    type: "ValidationError"
    type
    : 'ValidationError';
    message: string
    message
    : string;
    value: string
    value
    : string;
    }; const
    const validateEmail: (email: string) => Result.Result<string, ValidationError>
    validateEmail
    = (
    email: string
    email
    : string):
    import Result
    Result
    .
    type Result<T, E> = Result.Success<T> | Result.Failure<E>

    A union type representing either a success or a failure.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const doSomething = (): Result.Result<number, string> => {
      return Math.random() > 0.5
        ? { type: 'Success', value: 10 }
        : { type: 'Failure', error: 'Oops' };
    };
    @categoryCore Types
    Result
    <string,
    type ValidationError = {
        type: "ValidationError";
        message: string;
        value: string;
    }
    ValidationError
    > => {
    return
    import Result
    Result
    .
    const pipe: <string, Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, Result.Result<string, {
        readonly type: "ValidationError";
        readonly message: "Invalid email format";
        readonly value: string;
    }>>(a: string, ab: (a: string) => Result.Result<string, readonly StandardSchemaV1.Issue[]>, bc: (b: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, {
        readonly type: "ValidationError";
        readonly message: "Invalid email format";
        readonly value: string;
    }>) => Result.Result<...> (+25 overloads)
    pipe
    (
    email: string
    email
    ,
    import Result
    Result
    .
    const parse: <z.ZodString>(schema: z.ZodString) => (value: unknown) => Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]> (+1 overload)
    parse
    (
    import z
    z
    .
    function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)
    string
    ().
    ZodString.email(params?: string | z.core.$ZodCheckEmailParams): z.ZodString
    @deprecatedUse z.email() instead.
    email
    ()),
    import Result
    Result
    .
    const mapError: <Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, {
        readonly type: "ValidationError";
        readonly message: "Invalid email format";
        readonly value: string;
    }>(fn: (a: readonly StandardSchemaV1.Issue[]) => {
        readonly type: "ValidationError";
        readonly message: "Invalid email format";
        readonly value: string;
    }) => (result: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, {
        readonly type: "ValidationError";
        readonly message: "Invalid email format";
        readonly value: string;
    }> (+1 overload)
    mapError
    ((
    error: readonly StandardSchemaV1.Issue[]
    error
    ) => ({
    type: "ValidationError"
    type
    : 'ValidationError',
    message: "Invalid email format"
    message
    : 'Invalid email format',
    value: string
    value
    :
    email: string
    email
    ,
    })), ); };

    Why Use Custom Error Classes?

    While both approaches work, we recommend using custom Error classes for the following reasons:

    Stack Trace Availability

    Custom Error classes automatically capture stack traces, making debugging much easier:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    class
    class DatabaseError
    DatabaseError
    extends
    var Error: ErrorConstructor
    Error
    {
    public override readonly
    DatabaseError.name: "DatabaseError"
    name
    = 'DatabaseError';
    constructor(
    message: string
    message
    : string,
    options: ErrorOptions | undefined
    options
    ?: ErrorOptions) {
    super(
    message: string
    message
    ,
    options: ErrorOptions | undefined
    options
    );
    } } const
    const fetchUser: (id: string) => Result.Result<User, DatabaseError>
    fetchUser
    = (
    id: string
    id
    : string):
    import Result
    Result
    .
    type Result<T, E> = Result.Success<T> | Result.Failure<E>

    A union type representing either a success or a failure.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const doSomething = (): Result.Result<number, string> => {
      return Math.random() > 0.5
        ? { type: 'Success', value: 10 }
        : { type: 'Failure', error: 'Oops' };
    };
    @categoryCore Types
    Result
    <
    type User = {
        id: string;
        name: string;
    }
    User
    ,
    class DatabaseError
    DatabaseError
    > => {
    try { // Database operation... } catch (
    function (local var) error: unknown
    error
    ) {
    // The stack trace will show exactly where the error occurred return
    import Result
    Result
    .
    const fail: <DatabaseError>(error: DatabaseError) => Result.Result<never, DatabaseError> (+1 overload)
    fail
    (new
    constructor DatabaseError(message: string, options?: ErrorOptions): DatabaseError
    DatabaseError
    ('Failed to fetch user'));
    } };

    Error Chaining with Cause Option

    Custom Error classes support the cause option, allowing you to preserve the original error context:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    class
    class DatabaseError
    DatabaseError
    extends
    var Error: ErrorConstructor
    Error
    {
    public override readonly
    DatabaseError.name: "DatabaseError"
    name
    = 'DatabaseError';
    constructor(
    message: string
    message
    : string,
    options: ErrorOptions | undefined
    options
    ?: ErrorOptions) {
    super(
    message: string
    message
    ,
    options: ErrorOptions | undefined
    options
    );
    } } const
    const fetchUser: (id: string) => Result.Result<User, DatabaseError>
    fetchUser
    = (
    id: string
    id
    : string):
    import Result
    Result
    .
    type Result<T, E> = Result.Success<T> | Result.Failure<E>

    A union type representing either a success or a failure.

    @typeParamT - The type of the Success value.@typeParamE - The type of the Failure value.@example
    import { Result } from '@praha/byethrow';
    
    const doSomething = (): Result.Result<number, string> => {
      return Math.random() > 0.5
        ? { type: 'Success', value: 10 }
        : { type: 'Failure', error: 'Oops' };
    };
    @categoryCore Types
    Result
    <
    type User = {
        id: string;
        name: string;
    }
    User
    ,
    class DatabaseError
    DatabaseError
    > => {
    try { // Database operation... } catch (
    function (local var) error: unknown
    error
    ) {
    // Preserve the original error as cause return
    import Result
    Result
    .
    const fail: <DatabaseError>(error: DatabaseError) => Result.Result<never, DatabaseError> (+1 overload)
    fail
    (new
    constructor DatabaseError(message: string, options?: ErrorOptions): DatabaseError
    DatabaseError
    ('Failed to fetch user', {
    ErrorOptions.cause?: unknown
    cause
    :
    function (local var) error: unknown
    error
    })); } };

    For creating custom error classes efficiently, we recommend using @praha/error-factory. This library reduces boilerplate code and ensures consistent error structures.

    Installation

    npm
    yarn
    pnpm
    bun
    deno
    npm install @praha/error-factory

    Basic Usage with Result

    First, define the necessary custom error.

    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';
    class
    class ValidationError
    ValidationError
    extends
    ErrorFactory<"ValidationError", "Invalid input provided", ErrorFields>(props: {
        name?: "ValidationError" | undefined;
        message: "Invalid input provided" | ((fields: ErrorFields) => "Invalid input provided");
        fields?: ErrorFields | undefined;
    }): (new (options?: ErrorOptions) => Error & Readonly<{
        name: "ValidationError";
        message: "Invalid input provided";
    }>) & {
        name: "ValidationError";
    }

    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?: "ValidationError" | undefined
    name
    : 'ValidationError',
    message: "Invalid input provided" | ((fields: ErrorFields) => "Invalid input provided")
    message
    : 'Invalid input provided',
    }) {} class
    class QueryError
    QueryError
    extends
    ErrorFactory<"QueryError", "An error occurred while executing a query", {
        query: string;
    }>(props: {
        name?: "QueryError" | undefined;
        message: "An error occurred while executing a query" | ((fields: {
            query: string;
        }) => "An error occurred while executing a query");
        fields?: {
            query: string;
        } | undefined;
    }): (new (options: ErrorOptions & {
        query: string;
    }) => Error & Readonly<{
        name: "QueryError";
        message: "An error occurred while executing a query";
    }> & Readonly<{
        query: string;
    }>) & {
        name: "QueryError";
    }

    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?: "QueryError" | undefined
    name
    : 'QueryError',
    message: "An error occurred while executing a query" | ((fields: {
        query: string;
    }) => "An error occurred while executing a query")
    message
    : 'An error occurred while executing a query',
    fields?: {
        query: string;
    } | undefined
    fields
    :
    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
    .
    fields<{
        query: string;
    }>(): {
        query: string;
    }
    fields
    <{
    query: string
    query
    : string }>(),
    }) {} class
    class NotFoundError
    NotFoundError
    extends
    ErrorFactory<"NotFoundError", "Resource not found", ErrorFields>(props: {
        name?: "NotFoundError" | undefined;
        message: "Resource not found" | ((fields: ErrorFields) => "Resource not found");
        fields?: ErrorFields | undefined;
    }): (new (options?: ErrorOptions) => Error & Readonly<{
        name: "NotFoundError";
        message: "Resource not found";
    }>) & {
        name: "NotFoundError";
    }

    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?: "NotFoundError" | undefined
    name
    : 'NotFoundError',
    message: "Resource not found" | ((fields: ErrorFields) => "Resource not found")
    message
    : 'Resource not found',
    }) {}

    Next, create a function that returns the previously defined custom error together with a Result.

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    import {
    import z
    z
    } from 'zod';
    // Use custom errors in Result operations const
    const validateId: (id: string) => Result.Result<string, ValidationError>
    validateId
    = (
    id: string
    id
    : string) => {
    return
    import Result
    Result
    .
    const pipe: <string, Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, Result.Result<string, ValidationError>>(a: string, ab: (a: string) => Result.Result<string, readonly StandardSchemaV1.Issue[]>, bc: (b: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, ValidationError>) => Result.Result<string, ValidationError> (+25 overloads)
    pipe
    (
    id: string
    id
    ,
    import Result
    Result
    .
    const parse: <z.ZodString>(schema: z.ZodString) => (value: unknown) => Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]> (+1 overload)
    parse
    (
    import z
    z
    .
    function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)
    string
    ().
    _ZodString<$ZodStringInternals<string>>.startsWith(value: string, params?: string | z.core.$ZodCheckStartsWithParams): z.ZodString
    startsWith
    ('u')),
    import Result
    Result
    .
    const mapError: <Result.Result<string, readonly StandardSchemaV1<Input = unknown, Output = Input>.Issue[]>, ValidationError>(fn: (a: readonly StandardSchemaV1.Issue[]) => ValidationError) => (result: Result.Result<string, readonly StandardSchemaV1.Issue[]>) => Result.Result<string, ValidationError> (+1 overload)
    mapError
    ((
    error: readonly StandardSchemaV1.Issue[]
    error
    ) => new
    constructor ValidationError(options?: ErrorOptions): ValidationError
    ValidationError
    ({
    ErrorOptions.cause?: unknown
    cause
    :
    error: readonly StandardSchemaV1.Issue[]
    error
    })),
    ); }; const
    const executeQuery: (sql: string) => Result.ResultAsync<QueryResult, QueryError>
    executeQuery
    = (
    sql: string
    sql
    : string) => {
    return
    import Result
    Result
    .
    try<() => Promise<QueryResult>, QueryError>(options: {
        try: () => Promise<QueryResult>;
        catch: (error: unknown) => QueryError;
    }): Result.ResultAsync<QueryResult, QueryError> (+3 overloads)
    export try

    Executes a function that may throw and wraps the result in a Result or ResultAsync .

    You can use either a custom catch handler or rely on the safe: true option to assume the function cannot throw.

    @function@typeParamT - The function type to execute (sync or async) or a Promise type.@typeParamE - The error type to return if catch is used.@returnsA Result or ResultAsync wrapping the function's return value or the caught error.@example

    Sync try-catch

    import { Result } from '@praha/byethrow';
    
    const result = Result.try({
    try: () => {
    const x = Math.random() * 10 - 5;
    if (x < 0) throw new Error('Negative!');
    return x * 2;
    },
    catch: (error) => new Error('Oops!', { cause: error }),
    });
    
    // result is Result<number, Error>
    @example

    Sync safe

    import { Result } from '@praha/byethrow';
    
    const result = Result.try({
    safe: true,
    try: () => Math.random() + 1,
    });
    
    // result is Result<number, never>
    @example

    Async try-catch

    import { Result } from '@praha/byethrow';
    
    const result = Result.try({
    try: () => fetch('/api/data'),
    catch: (error) => new Error('Fetch failed', { cause: error }),
    });
    
    // result is ResultAsync<Response, Error>
    @example

    Async safe

    import { Result } from '@praha/byethrow';
    
    const result = Result.try({
    safe: true,
    try: () => Promise.resolve('ok'),
    });
    
    // result is ResultAsync<string, never>
    @categoryCreators
    try
    ({
    try: () => Promise<QueryResult>
    try
    : () =>
    const database: {
        query: (sql: string) => Promise<QueryResult>;
    }
    database
    .
    query: (sql: string) => Promise<QueryResult>
    query
    (
    sql: string
    sql
    ),
    catch: (error: unknown) => QueryError
    catch
    : (
    error: unknown
    error
    ) => new
    constructor QueryError(options: ErrorOptions & {
        query: string;
    }): QueryError
    QueryError
    ({
    query: string
    query
    :
    sql: string
    sql
    ,
    ErrorOptions.cause?: unknown
    cause
    :
    error: unknown
    error
    }),
    }); }; // Combine everything const
    const findUser: (id: string) => Result.ResultAsync<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>
    findUser
    = (
    id: string
    id
    : string) => {
    return
    import Result
    Result
    .
    const pipe: <Result.Result<string, ValidationError>, Result.ResultAsync<QueryResult, ValidationError | QueryError>, Result.ResultAsync<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>>(a: Result.Result<string, ValidationError>, ab: (a: Result.Result<string, ValidationError>) => Result.ResultAsync<QueryResult, ValidationError | QueryError>, bc: (b: Result.ResultAsync<...>) => Result.ResultAsync<...>) => Result.ResultAsync<...> (+25 overloads)
    pipe
    (
    const validateId: (id: string) => Result.Result<string, ValidationError>
    validateId
    (
    id: string
    id
    ),
    import Result
    Result
    .
    const andThen: <Result.Result<string, ValidationError>, Result.ResultAsync<QueryResult, QueryError>>(fn: (a: string) => Result.ResultAsync<QueryResult, QueryError>) => (result: Result.Result<string, ValidationError>) => Result.ResultAsync<QueryResult, ValidationError | QueryError> (+1 overload)
    andThen
    ((
    id: string
    id
    ) =>
    const executeQuery: (sql: string) => Result.ResultAsync<QueryResult, QueryError>
    executeQuery
    (`SELECT * FROM users WHERE id = '${
    id: string
    id
    }'`)),
    import Result
    Result
    .
    const andThen: <Result.ResultAsync<QueryResult, ValidationError | QueryError>, Result.Failure<NotFoundError> | Result.Success<{
        readonly id: string;
        readonly name: string;
    }>>(fn: (a: QueryResult) => Result.Failure<NotFoundError> | Result.Success<{
        readonly id: string;
        readonly name: string;
    }>) => (result: Result.ResultAsync<QueryResult, ValidationError | QueryError>) => Result.ResultAsync<...> (+1 overload)
    andThen
    ((
    row: QueryResult
    row
    ) => {
    if (!
    row: QueryResult
    row
    ) {
    return
    import Result
    Result
    .
    const fail: <NotFoundError>(error: NotFoundError) => Result.Result<never, NotFoundError> (+1 overload)
    fail
    (new
    constructor NotFoundError(options?: ErrorOptions): NotFoundError
    NotFoundError
    ());
    } return
    import Result
    Result
    .
    const succeed: <{
        readonly id: string;
        readonly name: string;
    }>(value: {
        readonly id: string;
        readonly name: string;
    }) => Result.Result<{
        readonly id: string;
        readonly name: string;
    }, never> (+1 overload)
    succeed
    ({
    id: string
    id
    :
    row: QueryResult
    row
    .
    string
    id
    ,
    name: string
    name
    :
    row: QueryResult
    row
    .
    string
    name
    });
    }), ); };

    Finally, execute the function and handle it appropriately.

    // Execute and handle errors
    const 
    const result: Result.Result<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>
    result
    = await
    const findUser: (id: string) => Result.ResultAsync<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>
    findUser
    ('u123');
    if (
    import Result
    Result
    .
    const isSuccess: <Result.Result<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>>(result: Result.Result<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>) => result is Result.Success<{
        readonly id: string;
        readonly name: string;
    }>

    Type guard to check if a Result is a Success .

    @function@typeParamR - The type of the result to check.@paramresult - The Result to check.@returnstrue if the result is a Success , otherwise false.@example
    import { Result } from '@praha/byethrow';
    
    const result: Result.Result<number, string> = { type: 'Success', value: 10 };
    if (Result.isSuccess(result)) {
      console.log(result.value); // Safe access to value
    }
    @categoryType Guards
    isSuccess
    (
    const result: Result.Result<{
        readonly id: string;
        readonly name: string;
    }, ValidationError | QueryError | NotFoundError>
    result
    )) {
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    (
    const result: Result.Success<{
        readonly id: string;
        readonly name: string;
    }>
    result
    .
    value: {
        readonly id: string;
        readonly name: string;
    }
    value
    );
    } else { // Handle each error type separately. switch (
    const result: Result.Failure<ValidationError | QueryError | NotFoundError>
    result
    .
    error: ValidationError | QueryError | NotFoundError
    error
    .
    Error.name: "ValidationError" | "QueryError" | "NotFoundError"
    name
    ) {
    case 'ValidationError':
    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
    ('Validation error:',
    const result: Result.Failure<ValidationError | QueryError | NotFoundError>
    result
    .
    error: ValidationError
    error
    .
    Error.message: "Invalid input provided"
    message
    );
    break; case 'QueryError':
    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
    ('Query error:',
    const result: Result.Failure<ValidationError | QueryError | NotFoundError>
    result
    .
    error: QueryError
    error
    .
    Error.message: "An error occurred while executing a query"
    message
    , 'Query:',
    const result: Result.Failure<ValidationError | QueryError | NotFoundError>
    result
    .
    error: QueryError
    error
    .
    query: string
    query
    );
    break; case 'NotFoundError':
    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
    ('Not found error:',
    const result: Result.Failure<ValidationError | QueryError | NotFoundError>
    result
    .
    error: NotFoundError
    error
    .
    Error.message: "Resource not found"
    message
    );
    break; } }