trycat
Version:
A lightweight, type-safe, zero-dependency implementation of the Result type.
223 lines (221 loc) • 10 kB
text/typescript
/**
* Interface for the Result type.
*/
interface ResultBase<T, TErr> {
/**
* A type guard that checks if this Result is Ok. If it is, the Result is cast to Ok.
* @returns true if this Result is Ok, false otherwise.
*/
isOk(): this is Ok<T>;
/**
* A type guard that checks if this Result is Err. If it is, the Result is cast to Err.
* @returns true if this Result is Err, false otherwise.
*/
isErr(): this is Err<TErr>;
/**
* Calls the provided function with the contained value if this Result is Ok.
* Nothing is performed otherwise.
*
* @param f - The function to be called if this Result is Ok. First arg will receive the contained value.
*
* @returns This Result.
*/
inspect(f: (value: T) => unknown): this;
/**
* Calls the provided function with the contained value if this Result is Err.
* Nothing is performed otherwise.
*
* @param f - The function to be called if this Result is Err. First arg will receive the contained error.
*
* @returns This Result.
*/
inspectErr(f: (error: TErr) => unknown): this;
/**
* If this Result is Ok, calls the given mapper function with the current contained value
* and returns a new Result containing the value returned by the mapper function.
*
* @param mapper - The function that maps the current contained value to another value.
*
* @returns A new Result object containing the value returned by the mapper function, or this if this is Err.
*/
map<TNew>(mapper: (value: T) => TNew): this | Result<TNew, TErr>;
/**
* If this Result is Ok, it does the same thing as {@link map}.
* Otherwise, returns the given default value.
*
* @param def - The default value to be returned if this Result is Err.
* @param mapper - The function that maps the current contained value to another value if this Result is Ok.
*
* @returns A new Result object containing the value returned by the mapped function if this is Ok, otherwise the default value.
*/
mapOr<TNew, TDef>(def: TDef, mapper: (value: T) => TNew): TNew | TDef;
/**
* Same as {@link mapOr}, except if this is Err, the default value is returned lazily by the first callback
* which receives the contained error and returns the default value.
*
* @param errMapper - The function that maps the contained error value to a default value if this Result is Err.
* @param mapper - The function that maps the contained value to a new value if this Result is Ok.
*
* @returns The value returned by the error mapper if this is Err; The value returned by the value mapper if this is Ok.
*/
mapOrElse<TNew, TDef>(errMapper: (error: TErr) => TDef, mapper: (value: T) => TNew): TNew | TDef;
/**
* If this Result is Err, calls the given mapper with the current error value,
* then returns a new Result containing the new error value returned by the mapper.
* Otherwise, nothing is performed and this is returned.
*
* @param mapper - The function that maps the contained error value to another error value.
*
* @returns A new Result containing the error value returned by the mapper if this is Err, or this Result otherwise.
*/
mapErr<TNewErr>(mapper: (error: TErr) => TNewErr): this | Result<T, TNewErr>;
/**
* @returns the given Result if this Result is Err, otherwise this.
*/
or<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(res: TR): this | TR;
/**
* Calls the given callback with the contained error value if this Result is Err.
*
* @returns the Result returned by the given callback, otherwise this Result
*/
orElse<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (error: TErr) => TR): this | TR;
/**
* @returns the given Result if this Result is Ok, otherwise this.
*/
and<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(res: TR): this | TR;
/**
* Calls the given callback with the contained value if this Result is Ok.
*
* @returns the Result returned by the given callback, otherwise this Result
*/
andThen<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (value: T) => TR): this | TR;
/**
* @returns the contained value if this Result is Ok.
* @throws if this Result is Err, with the error message provided by the containing error.
*/
unwrap(): T;
/**
* @returns the contained value if this Result is Ok or the given value otherwise.
*/
unwrapOr<TDef>(def: TDef): T | TDef;
/**
* Calls the given function with the contained error value and returns the value returned by the function if this Result is Err. Otherwise, returns the contained value.
*
* @returns The contained value if this Result is Ok or the value returned by the given function otherwise.
*/
unwrapOrElse<TDef>(op: (error: TErr) => TDef): T | TDef;
/**
* Returns the contained value if this Result is Ok, otherwise throws with the given error message.
*
* @param message - The error message to be displayed if this Result is Err.
*
* @returns The contained value if this Result is Ok.
* @throws An error with the given error message if this Result is Err.
* The error message includes the provided message, as well as the content of the containing error.
*/
expect(message: string): T;
/**
* @returns the contained error value if this Result is Err.
* @throws the contained value as the error message if this Result is Ok
*/
unwrapErr(): TErr;
/**
* Returns the contained error value if this Result is Err, otherwise throws with the given error message.
*
* @param message - The error message to be displayed if this Result is Ok.
*
* @returns The contained error value if this Result is Err.
* @throws An error with the given error message and the content of the containing error as the message if this Result is Ok.
*/
expectErr(message: string): TErr;
}
/**
* Stores the result of a successful operation.
* Access the contained via {@link Ok.value}.
* Refer to {@link ResultBase} for available methods.
*
* @see ResultBase
*/
declare class Ok<T> implements ResultBase<T, never> {
readonly value: T;
constructor(value: T);
isOk(): this is Ok<T>;
isErr(): this is Err<never>;
inspect(f: (value: T) => unknown): this;
inspectErr(f: (error: never) => unknown): this;
map<TNew>(mapper: (value: T) => TNew): Ok<TNew>;
mapOr<TNew, TDef>(def: TDef, mapper: (result: T) => TNew): TNew;
mapOrElse<TNew, TDef>(errMapper: (error: never) => TDef, mapper: (value: T) => TNew): TNew;
mapErr<TNewErr>(mapper: (error: never) => TNewErr): this;
or<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(other: TR): this;
orElse<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (error: never) => TR): this;
and<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(other: TR): TR;
andThen<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (value: T) => TR): TR;
unwrap(): T;
unwrapOr<TDef>(def: TDef): T;
unwrapOrElse<TDef>(op: (error: never) => TDef): T;
expect(msg: string): T;
unwrapErr(): never;
expectErr(message: string): never;
}
/**
* Stores the error of a failed operation.
* Access the error via {@link Err.error}.
* Refer to {@link ResultBase} for available methods.
*
* @see ResultBase
*/
declare class Err<TErr> implements ResultBase<never, TErr> {
readonly error: TErr;
constructor(error: TErr);
isOk(): this is Ok<never>;
isErr(): this is Err<TErr>;
inspect(f: (value: never) => unknown): this;
inspectErr(f: (error: TErr) => unknown): this;
map<TNew>(mapper: (value: never) => TNew): this;
mapOr<TNew, TDef>(def: TDef, mapper: (value: never) => TNew): TDef;
mapOrElse<TNew, TDef>(errMapper: (error: TErr) => TDef, mapper: (value: never) => TNew): TDef;
mapErr<TNewErr>(mapper: (error: TErr) => TNewErr): Err<TNewErr>;
or<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(other: TR): TR;
orElse<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (error: TErr) => TR): TR;
and<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(other: TR): this;
andThen<TOther, TOtherErr, TR extends Result<TOther, TOtherErr>>(op: (value: never) => TR): this;
unwrap(): never;
unwrapOr<TDef>(def: TDef): TDef;
unwrapOrElse<TDef>(op: (error: TErr) => TDef): TDef;
expect(message: string): never;
unwrapErr(): TErr;
expectErr(message: string): TErr;
}
/**
* Represents the result of a fail-able operation.
* A successful operation returns {@link Ok}, and a failed operation returns {@link Err}.
*
* Refer to {@link ResultBase} for methods available on a {@link Result}.
*
* @see ResultBase
*/
type Result<T, TErr> = Ok<T> | Err<TErr>;
declare function ok(): Ok<void>;
declare function ok<T>(value: T): Ok<T>;
declare function err(): Err<void>;
declare function err<T>(error: T): Err<T>;
/**
* Calls the given function, catches any thrown error into an {@link Err},
* and wraps the returned value with an {@link Ok} if nothing goes wrong.
*/
declare function trys<T>(fn: () => T): Result<T, unknown>;
declare function trys(fn: () => void): Result<void, unknown>;
/**
* Stores the result of the given {@link Promise} into a {@link Result}.
* If the promise fails, {@link Err} is returned. If the promise succeeds, {@link Ok} is returned.
*
* @example
* const res = await tryp(fetch("/my/api")).mapErr((err) => apiError(err))
* if (res.isErr()) {
* return err(res.error)
* }
*/
declare function tryp(promise: Promise<void>): Promise<Result<void, unknown>>;
declare function tryp<T>(promise: Promise<T>): Promise<Result<T, unknown>>;
export { Err, Ok, type Result, type ResultBase, err, ok, tryp, trys };