import { NoOptionPromiseShouldUseMapOrElse, Option, OptionLike, OptionLikeShouldUseMapOption, OptionPromise, OptionPromiseLike, OptionPromiseShouldUseMapOption } from "./mod"; /** * Type `Result` represents an result value: every `Result` is either `Ok` and * contains a value of type `T`, or `Err`, which holds an error value of type `E`. * When using `Result` throwing `Errors` is no longer necessary. Just make sure * that `Result` values are properly mapped to other values, or other error types. * * @example * ```typescript * class CannotDivideByZero {} * * function divide( * numerator: number, * denominator: number, * ): Result { * if (denominator === 0) { * return Err(new CannotDivideByZero()); * } else { * return Ok(numerator / denominator); * } * } * * // The return value of the function is always a result * for (const result of [divide(7, 0), divide(2.0, 3.0)]) { * result.mapOrElse( * (_) => console.error("Cannot divide by zero"), * (ok) => console.log(`Result: ${ok}`), * ); * } * // "Cannot divide by zero" * // "Result: 0.6666666666666666" * ``` */ export interface Result { [Symbol.iterator]: () => IterableIterator; /** * Returns res if the result is Ok, otherwise returns the Err value of self. * * Arguments passed to and are eagerly evaluated; if you are passing the result * of a function call, it is recommended to use {@linkcode andThen}, which is lazily evaluated. */ and(res: Result): Result; /** * Calls op if the result is Ok, otherwise returns the Err value of self. * * This function can be used for control flow based on Result values. */ andThen(op: (val: T) => ResultPromiseLike): ResultPromise; andThen(op: (val: T) => Result): Result; /** * Converts from Result to Option. * * Converts self into an {@linkcode Option}, consuming self, and discarding the success value, if any. */ err(): Option; isOk(): boolean; isErr(): boolean; /** * Maps an Result to an Result by applying a function to a contained {@linkcode Ok} value, * leaving an {@linkcode Err} value untouched. * * This function can be used to compose the results of two functions. */ map(fn: (value: T) => Promise): ResultPromise; map(fn: (value: T) => U): Result; /** * Maps a Result to Result by applying a function to a contained Err value, leaving an Ok value untouched. * * This function can be used to pass through a successful result while handling an error. */ mapErr(fn: (err: E) => Promise): ResultPromise; mapErr(fn: (err: E) => F): Result; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * When U is `Promise>`, the actual return type will be `ResultPromise`. * U should not be `Promise

` where P is not Result, @see {@linkcode mapOrElse} or @see {@linkcode mapOption}for returning non-Result promises */ mapResult(def: (err: E) => U, fn: (value: T) => U): ResultMapResult; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * When U is `Promise>`, the actual return type will be `OptionPromise`. * U should not be `Promise

` where P is not Option, @see {@linkcode mapOrElse} or @see {@linkcode mapResult}for returning non-Option promises */ mapOption(def: (err: E) => U, fn: (value: T) => U): ResultMapOption; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * U should not be `Promise>` @see {@linkcode mapOption}, nor `Promise>`{@linkcode mapResult} for * returning promises to Option or Result */ mapOrElse(def: (err: E) => U, fn: (value: T) => U): ResultMapOrElse; /** * Converts from {@linkcode Result} to {@linkcode Option}. * * Converts self into an {@linkcode Option}, consuming self, and discarding the error, if any. */ ok(): Option; /** * Returns res if the result is Err, otherwise returns the Ok value of self. * * Arguments passed to or are eagerly evaluated; if you are passing the result of a function call, * it is recommended to use {@linkcode orElse}, which is lazily evaluated. */ or(res: Result): Result; /** * Returns the result if it contains a value, otherwise calls f and returns the result. */ orElse(fn: (err: E) => Promise>): ResultPromise; orElse(fn: (err: E) => Result): Result; /** * Returns the contained Ok value or a provided default. * * Arguments passed to unwrap_or are eagerly evaluated; * if you are passing the result of a function call, * it is recommended to use {@linkcode unwrapOrElse}, which is lazily evaluated. */ unwrapOr(def: T): T; /** * Returns the contained Ok value or computes it from a closure. */ unwrapOrElse(def: (err: E) => T): T; unwrapOrElse(def: (err: E) => Promise): Promise | T; } /** * `Result` has several combinator methods, like andThen, orElse * and map. Those methods accept one or more callback functions that can be async. * * The examples below demonstrates how Promises and async callbacks can be combined * with the andThen and mapOrElse. * * @example * * ```typescript * type ToDo = { userId: number; id: number; title: string; completed: boolean }; * * function doFetch(url: string): ResultPromise { * return Ok( * fetch(url) * .then( * Ok, * (err) => Err(err.toString()), * ), * ); * } * * function fetchJson(url: string): ResultPromise { * return doFetch(url) * .andThen(async (response) => { * if (response.ok) return Ok(await response.json()); * else {return Err( * `${response.status} ${response.statusText}: ${await response.text()}`, * );} * }); * } * * fetchJson("https:///jsonplaceholder.typicode.com/todos/1") * .mapOrElse( * (err) => console.error("Failed:", err), * (todo) => console.log("Success:", todo.title), * ); * ``` */ export interface ResultPromise extends Promise> { /** * Returns res if the result is Ok, otherwise returns the Err value of self. * * Arguments passed to and are eagerly evaluated; if you are passing the result * of a function call, it is recommended to use {@linkcode andThen}, which is lazily evaluated. */ and(res: Result): ResultPromise; /** * Calls op if the result is Ok, otherwise returns the Err value of self. * * This function can be used for control flow based on Result values. */ andThen(op: (value: T) => ResultLike): ResultPromise; /** * Converts from Result to Option. * * Converts self into an {@linkcode Option}, consuming self, and discarding the success value, if any. */ err(): OptionPromise; isOk(): Promise; isErr(): Promise; /** * Maps an Result to an Result by applying a function to a contained {@linkcode Ok} value, * leaving an {@linkcode Err} value untouched. * * This function can be used to compose the results of two functions. */ map(fn: (value: T) => Promise): ResultPromise; map(fn: (value: T) => U): ResultPromise; /** * Maps a Result to Result by applying a function to a contained Err value, leaving an Ok value untouched. * * This function can be used to pass through a successful result while handling an error. */ mapErr(fn: (err: E) => Promise): ResultPromise; mapErr(fn: (err: E) => F): ResultPromise; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * When U is `Promise>`, the actual return type will be `OptionPromise`. * U should not be `Promise

` where P is not Option, @see {@linkcode mapOrElse} or @see {@linkcode mapResult}for returning non-Option promises */ mapResult(def: (err: E) => U, fn: (value: T) => U): ResultPromiseMapResult; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * When U is `Promise>`, the actual return type will be `OptionPromise`. * U should not be `Promise

` where P is not Option, @see {@linkcode mapOrElse} or @see {@linkcode mapResult}for returning non-Option promises */ mapOption(def: (err: E) => U, fn: (value: T) => U): ResultPromiseMapOption; /** * Computes a default function result (if Err), or applies a different function to the contained value (if Ok). * * U should not be `Promise>` @see {@linkcode mapOption}, nor `Promise>`{@linkcode mapResult} for * returning promises to Option or Result */ mapOrElse(def: (err: E) => U, fn: (value: T) => U): ResultPromiseMapOrElse; /** * Converts from {@linkcode Result} to {@linkcode Option}. * * Converts self into an {@linkcode Option}, consuming self, and discarding the error, if any. */ ok(): OptionPromise; /** * Returns res if the result is Err, otherwise returns the Ok value of self. * * Arguments passed to or are eagerly evaluated; if you are passing the result of a function call, * it is recommended to use {@linkcode orElse}, which is lazily evaluated. */ or(res: Result): ResultPromise; /** * Returns the result if it contains a value, otherwise calls f and returns the result. */ orElse(fn: (err: E) => Promise>): ResultPromise; orElse(fn: (err: E) => Result): ResultPromise; /** * Returns the contained Ok value or a provided default. * * Arguments passed to unwrap_or are eagerly evaluated; * if you are passing the result of a function call, * it is recommended to use {@linkcode unwrapOrElse}, which is lazily evaluated. */ unwrapOr(def: T): Promise; /** * Returns the contained Ok value or computes it from a closure. */ unwrapOrElse(def: (err: E) => T): Promise; unwrapOrElse(def: (err: E) => Promise): Promise; } export interface UnwrapableResult extends Result { type: symbol; unwrap(): T; } export type ResultPromiseShouldUseMapResult = "To return a Promise to a Result, use mapResult"; export type ResultLikeShouldUseMapResult = "To return (a Promise to) a Result, use mapResult"; export type NoResultPromiseShouldUseMapOrElse = "To return a promise to anything other than Result, use mapOrElse"; /** * Value is something that implements an interface with * the `ResultPromise` combinators e.g., `andThen`, `orElse`, `map` and `mapOrElse` * as well as the Promise interface */ export type ResultPromiseLike = Promise> | ResultPromise; /** * Value is something that implements an interface with * the `Result` combinators e.g., `andThen`, `orElse`, `map` and `mapOrElse` */ export type ResultLike = Result | ResultPromiseLike; export type OkFrom = U extends ResultPromiseLike ? ResultPromise : U extends Promise ? ResultPromise : U extends Result ? Result : U extends false | true ? Result : Result; export type ErrFrom = E extends ResultPromiseLike ? ResultPromise : E extends Promise ? ResultPromise : E extends Result ? Result : E extends false | true ? Result : Result; export type ResultMapOrElse = T extends ResultPromiseLike ? ResultPromiseShouldUseMapResult : T extends OptionLike ? OptionPromiseShouldUseMapOption : T; export type ResultPromiseMapOrElse = T extends ResultLike ? ResultLikeShouldUseMapResult : T extends OptionLike ? OptionLikeShouldUseMapOption : T extends Promise ? Promise

: Promise; export type ResultMapOption = T extends OptionPromiseLike ? OptionPromise : T extends ResultPromiseLike ? ResultPromiseShouldUseMapResult : T extends Promise ? NoResultPromiseShouldUseMapOrElse : T; export type ResultPromiseMapOption = T extends OptionLike ? OptionPromise : T extends ResultLike ? ResultLikeShouldUseMapResult : T extends Promise ? NoResultPromiseShouldUseMapOrElse : Promise; export type ResultMapResult = T extends ResultPromiseLike ? ResultPromise : T extends OptionPromiseLike ? OptionPromiseShouldUseMapOption : T extends Promise ? NoResultPromiseShouldUseMapOrElse : T; export type ResultPromiseMapResult = T extends ResultLike ? ResultPromise : T extends OptionLike ? OptionLikeShouldUseMapOption : T extends Promise ? NoOptionPromiseShouldUseMapOrElse : Promise;