• English
  • Unwrapping Results

    Sometimes you need to extract the actual value from a Result, exiting the Result "world" back into plain values. The unwrap and unwrapError functions help with this.

    Extracting Success Values with unwrap

    The unwrap function extracts the success value from a Result:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<42, never>
    result
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    const
    const value: 42
    value
    =
    import Result
    Result
    .
    const unwrap: <Result.Result<42, never>>(result: Result.Result<42, never>) => 42 (+3 overloads)
    unwrap
    (
    const result: Result.Result<42, never>
    result
    );
    // value: 42

    What Happens on Failure?

    If the Result is a Failure and no default is provided, unwrap throws the error:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<never, Error>
    result
    =
    import Result
    Result
    .
    const fail: <Error>(error: Error) => Result.Result<never, Error> (+1 overload)
    fail
    (new
    var Error: ErrorConstructor
    new (message?: string, options?: ErrorOptions) => Error (+1 overload)
    Error
    ('Something went wrong'));
    const
    const value: never
    value
    =
    import Result
    Result
    .
    const unwrap: <Result.Result<never, Error>>(result: Result.Result<never, Error>) => never (+3 overloads)
    unwrap
    (
    const result: Result.Result<never, Error>
    result
    );
    // Throws: Error('Something went wrong')

    Providing a Default Value

    You can provide a default value to avoid throwing:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<never, "error">
    result
    =
    import Result
    Result
    .
    const fail: <"error">(error: "error") => Result.Result<never, "error"> (+1 overload)
    fail
    ('error');
    const
    const value: 0
    value
    =
    import Result
    Result
    .
    const unwrap: <Result.Result<never, "error">, 0>(result: Result.Result<never, "error">, defaultValue: 0) => 0 (+3 overloads)
    unwrap
    (
    const result: Result.Result<never, "error">
    result
    , 0);
    // value: 0 (default value)
    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const success: Result.Result<42, never>
    success
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    const
    const value: 42 | 0
    value
    =
    import Result
    Result
    .
    const unwrap: <Result.Result<42, never>, 0>(result: Result.Result<42, never>, defaultValue: 0) => 42 | 0 (+3 overloads)
    unwrap
    (
    const success: Result.Result<42, never>
    success
    , 0);
    // value: 42 (success value, default ignored)

    Extracting Error Values with unwrapError

    The unwrapError function is the opposite—it extracts the error value:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<never, "Something went wrong">
    result
    =
    import Result
    Result
    .
    const fail: <"Something went wrong">(error: "Something went wrong") => Result.Result<never, "Something went wrong"> (+1 overload)
    fail
    ('Something went wrong');
    const
    const error: "Something went wrong"
    error
    =
    import Result
    Result
    .
    const unwrapError: <Result.Result<never, "Something went wrong">>(result: Result.Result<never, "Something went wrong">) => "Something went wrong" (+3 overloads)
    unwrapError
    (
    const result: Result.Result<never, "Something went wrong">
    result
    );
    // error: 'Something went wrong'

    What Happens on Success?

    If the Result is a Success and no default is provided, unwrapError throws the value:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<42, never>
    result
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    const
    const error: never
    error
    =
    import Result
    Result
    .
    const unwrapError: <Result.Result<42, never>>(result: Result.Result<42, never>) => never (+3 overloads)
    unwrapError
    (
    const result: Result.Result<42, never>
    result
    );
    // Throws: 42

    Providing a Default Error

    You can provide a default value to avoid throwing:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const result: Result.Result<42, never>
    result
    =
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42);
    const
    const error: "No error"
    error
    =
    import Result
    Result
    .
    const unwrapError: <Result.Result<42, never>, "No error">(result: Result.Result<42, never>, defaultValue: "No error") => "No error" (+3 overloads)
    unwrapError
    (
    const result: Result.Result<42, never>
    result
    , 'No error');
    // error: 'No error' (default value)
    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const failure: Result.Result<never, "Something went wrong">
    failure
    =
    import Result
    Result
    .
    const fail: <"Something went wrong">(error: "Something went wrong") => Result.Result<never, "Something went wrong"> (+1 overload)
    fail
    ('Something went wrong');
    const
    const error: "Something went wrong" | "No error"
    error
    =
    import Result
    Result
    .
    const unwrapError: <Result.Result<never, "Something went wrong">, "No error">(result: Result.Result<never, "Something went wrong">, defaultValue: "No error") => "Something went wrong" | "No error" (+3 overloads)
    unwrapError
    (
    const failure: Result.Result<never, "Something went wrong">
    failure
    , 'No error');
    // error: 'Something went wrong' (failure value, default ignored)

    Working with Async Results

    Both unwrap and unwrapError work with ResultAsync:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const asyncResult: Result.ResultAsync<number, never>
    asyncResult
    =
    import Result
    Result
    .
    const succeed: <Promise<number>>(value: Promise<number>) => Result.ResultAsync<number, never> (+1 overload)
    succeed
    (
    var Promise: PromiseConstructor

    Represents the completion of an asynchronous operation

    Promise
    .
    PromiseConstructor.resolve<number>(value: number): Promise<number> (+2 overloads)

    Creates a new resolved promise for the provided value.

    @paramvalue A promise.@returnsA promise whose internal state matches the provided promise.
    resolve
    (42));
    // Returns a Promise const
    const value: number
    value
    = await
    import Result
    Result
    .
    const unwrap: <Result.ResultAsync<number, never>>(result: Result.ResultAsync<number, never>) => Promise<number> (+3 overloads)
    unwrap
    (
    const asyncResult: Result.ResultAsync<number, never>
    asyncResult
    );
    // value: 42

    With default:

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const asyncResult: Result.ResultAsync<never, string>
    asyncResult
    =
    import Result
    Result
    .
    const fail: <Promise<string>>(error: Promise<string>) => Result.ResultAsync<never, string> (+1 overload)
    fail
    (
    var Promise: PromiseConstructor

    Represents the completion of an asynchronous operation

    Promise
    .
    PromiseConstructor.resolve<string>(value: string): Promise<string> (+2 overloads)

    Creates a new resolved promise for the provided value.

    @paramvalue A promise.@returnsA promise whose internal state matches the provided promise.
    resolve
    ('error'));
    const
    const value: 0
    value
    = await
    import Result
    Result
    .
    const unwrap: <Result.ResultAsync<never, string>, 0>(result: Result.ResultAsync<never, string>, defaultValue: 0) => Promise<0> (+3 overloads)
    unwrap
    (
    const asyncResult: Result.ResultAsync<never, string>
    asyncResult
    , 0);
    // value: 0

    When to Use unwrap

    Good Use Cases

    Use unwrap at the boundaries of your application—such as HTTP handlers, CLI entry points-where you need to exit the Result world and return plain values to the outside world.

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    const
    const handleRequest: (req: Request) => Promise<Response>
    handleRequest
    = async (
    req: Request
    req
    : Request):
    interface Promise<T>

    Represents the completion of an asynchronous operation

    Promise
    <Response> => {
    return await
    import Result
    Result
    .
    const pipe: <Result.ResultAsync<number, "NotFound" | "Unexpected">, Result.ResultAsync<Response, "NotFound" | "Unexpected">, Result.ResultAsync<Response, "Unexpected">, Promise<Response>>(a: Result.ResultAsync<number, "NotFound" | "Unexpected">, ab: (a: Result.ResultAsync<number, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "NotFound" | "Unexpected">, bc: (b: Result.ResultAsync<Response, "NotFound" | "Unexpected">) => Result.ResultAsync<...>, cd: (c: Result.ResultAsync<...>) => Promise<...>) => Promise<...> (+25 overloads)
    pipe
    (
    const processRequest: (req: Request) => Result.ResultAsync<number, "NotFound" | "Unexpected">
    processRequest
    (
    req: Request
    req
    ),
    import Result
    Result
    .
    const map: <Result.ResultAsync<number, "NotFound" | "Unexpected">, Response>(fn: (a: number) => Response) => (result: Result.ResultAsync<number, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "NotFound" | "Unexpected"> (+1 overload)
    map
    ((
    result: number
    result
    ) => {
    return new
    var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

    The Response interface of the Fetch API represents the response to a request.

    MDN Reference

    Response
    (
    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
    (
    result: number
    result
    ), {
    ResponseInit.status?: number | undefined
    status
    : 200 });
    }),
    import Result
    Result
    .
    const orElse: <Result.ResultAsync<Response, "NotFound" | "Unexpected">, Result.Success<Response> | Result.Failure<"Unexpected">>(fn: (a: "NotFound" | "Unexpected") => Result.Success<Response> | Result.Failure<"Unexpected">) => (result: Result.ResultAsync<Response, "NotFound" | "Unexpected">) => Result.ResultAsync<Response, "Unexpected"> (+1 overload)
    orElse
    ((
    error: "NotFound" | "Unexpected"
    error
    ) => {
    switch (
    error: "NotFound" | "Unexpected"
    error
    ) {
    case 'NotFound': return
    import Result
    Result
    .
    const succeed: <Response>(value: Response) => Result.Result<Response, never> (+1 overload)
    succeed
    (new
    var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

    The Response interface of the Fetch API represents the response to a request.

    MDN Reference

    Response
    ('Not Found', {
    ResponseInit.status?: number | undefined
    status
    : 404 }));
    default: return
    import Result
    Result
    .
    const fail: <"Unexpected">(error: "Unexpected") => Result.Result<never, "Unexpected"> (+1 overload)
    fail
    (
    error: "Unexpected"
    error
    );
    } }), // Unexpected errors are thrown here and can be detected // by infrastructure-level error monitoring tools like Sentry or CloudWatch.
    import Result
    Result
    .
    const unwrap: <Result.ResultAsync<Response, "Unexpected">>() => (result: Result.ResultAsync<Response, "Unexpected">) => Promise<Response> (+3 overloads)
    unwrap
    (),
    ); };

    Avoid Using unwrap

    Avoid calling unwrap in the middle of your logic. Doing so exits the Result "world" prematurely, losing the benefits of type-safe error handling. Instead, keep values wrapped in Results and use combinators like map, flatMap, or orElse to transform them.

    import { 
    import Result
    Result
    } from '@praha/byethrow';
    // ❌ Don't do this const
    const bad: number
    bad
    =
    import Result
    Result
    .
    const unwrap: <Result.Result<42, never>>(result: Result.Result<42, never>) => 42 (+3 overloads)
    unwrap
    (
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42)) * 2;
    // ✅ Do this instead const
    const good: Result.Result<number, never>
    good
    =
    import Result
    Result
    .
    const pipe: <Result.Result<42, never>, Result.Result<number, never>>(a: Result.Result<42, never>, ab: (a: Result.Result<42, never>) => Result.Result<number, never>) => Result.Result<number, never> (+25 overloads)
    pipe
    (
    import Result
    Result
    .
    const succeed: <42>(value: 42) => Result.Result<42, never> (+1 overload)
    succeed
    (42),
    import Result
    Result
    .
    const map: <Result.Result<42, never>, number>(fn: (a: 42) => number) => (result: Result.Result<42, never>) => Result.Result<number, never> (+1 overload)
    map
    ((
    x: 42
    x
    ) =>
    x: 42
    x
    * 2),
    );

    References

    FunctionPurpose
    unwrap(result)Extracts the success value from a Result, or throws/returns default on failure
    unwrapError(result)Extracts the error value from a Result, or throws/returns default on success