import { toString } from './utils' ; import { Option , None , Some } from './option' ; interface BaseResult < T , E > extends Iterable < T extends Iterable < infer U > ? U : never > { /** `true` when the result is Ok */ readonly ok : boolean ; /** `true` when the result is Err */ readonly err : boolean ; param msg expect ( msg ) : T ; /**
     * Returns the contained `Ok` value.
     * Because this function may throw, its use is generally discouraged.
     * Instead, prefer to handle the `Err` case explicitly.
     *
     * Throws if the value is an `Err`, with a message provided by the `Err`'s value.
     */ unwrap ( ) : T ; see unwrapOr deprecated else < T2 > ( val ) : T | T2 ; /**
     * Returns the contained `Ok` value or a provided default.
     *
     *  (This is the `unwrap_or` in rust)
     */ unwrapOr < T2 > ( val ) : T | T2 ; /**
     * Calls `mapper` 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 < T2 > ( mapper ) : Result < T2 , E > ; andThen < E2 > ( mapper ) : Result < T , E | E2 > ; andThen < T2 , E2 > ( mapper ) : Result < T2 , E | E2 > ; andThen < T2 , E2 > ( mapper ) : Result < T2 , E | E2 > ; /**
     * Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a contained `Ok` value,
     * leaving an `Err` value untouched.
     *
     * This function can be used to compose the results of two functions.
     */ map < U > ( mapper ) : Result < U , E > ; /**
     * Maps a `Result<T, E>` to `Result<T, F>` 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 < F > ( mapper ) : Result < T , F > ; /**
     *  Converts from `Result<T, E>` to `Option<T>`, discarding the error if any
     *
     *  Similar to rust's `ok` method
     */ toOption ( ) : Option < T > ; } /**
 * Contains the error value
 */ export class ErrImpl < E > implements BaseResult < never , E > { /** An empty Err */ static readonly EMPTY = new ErrImpl < void > ( undefined ) ; readonly ok ! : false ; readonly err ! : true ; readonly val ! : E ; private readonly _stack ! : string ; [ Symbol . iterator ] ( ) { return { next ( ) { return { done : true , value : undefined ! } ; } , } ; } constructor ( val ) { if ( ! ( this instanceof ErrImpl ) ) { return new ErrImpl ( val ) ; } this . ok = false ; this . err = true ; this . val = val ; const stackLines = new Error ( ) . stack ! . split ( '\n' ) . slice ( 2 ) ; if ( stackLines && stackLines . length > 0 && stackLines [ 0 ] . includes ( 'ErrImpl' ) ) { stackLines . shift ( ) ; } this . _stack = stackLines . join ( '\n' ) ; } deprecated see unwrapOr else < T2 > ( val ) { return val ; } unwrapOr < T2 > ( val ) { return val ; } expect ( msg ) { throw new Error ( `${ msg } - Error: ${ toString ( this . val ) }\n${ this . _stack }` ) ; } unwrap ( ) { throw new Error ( `Tried to unwrap Error: ${ toString ( this . val ) }\n${ this . _stack }` ) ; } map ( _mapper ) { return this ; } andThen ( op ) { return this ; } mapErr < E2 > ( mapper ) { return new Err ( mapper ( this . val ) ) ; } toOption ( ) { return None ; } toString ( ) { return `Err(${ toString ( this . val ) })` ; } get stack ( ) : string | undefined { return `${ this }\n${ this . _stack }` ; } } export const Err = ErrImpl as typeof ErrImpl & ( < E > ( err : E ) => Err < E > ) ; export type Err < E > = ErrImpl < E > ; /**
 * Contains the success value
 */ export class OkImpl < T > implements BaseResult < T , never > { static readonly EMPTY = new OkImpl < void > ( undefined ) ; readonly ok ! : true ; readonly err ! : false ; readonly val ! : T ; /**
     * Helper function if you know you have an Ok<T> and T is iterable
     */ [ Symbol . iterator ] ( ) { const obj = Object ( this . val ) as Iterable < any > ; return Symbol . iterator in obj ? obj [ Symbol . iterator ] ( ) : { next ( ) { return { done : true , value : undefined ! } ; } , } ; } constructor ( val ) { if ( ! ( this instanceof OkImpl ) ) { return new OkImpl ( val ) ; } this . ok = true ; this . err = false ; this . val = val ; } see unwrapOr deprecated else ( _val ) { return this . val ; } unwrapOr ( _val ) { return this . val ; } expect ( _msg ) { return this . val ; } unwrap ( ) { return this . val ; } map < T2 > ( mapper ) { return new Ok ( mapper ( this . val ) ) ; } andThen < T2 > ( mapper ) ; andThen < E2 > ( mapper ) ; andThen < T2 , E2 > ( mapper ) ; andThen < T2 , E2 > ( mapper ) { return mapper ( this . val ) ; } mapErr ( _mapper ) { return this ; } toOption ( ) { return Some ( this . val ) ; } /**
     * Returns the contained `Ok` value, but never throws.
     * Unlike `unwrap()`, this method doesn't throw and is only callable on an Ok<T>
     *
     * Therefore, it can be used instead of `unwrap()` as a maintainability safeguard
     * that will fail to compile if the error type of the Result is later changed to an error that can actually occur.
     *
     * (this is the `into_ok()` in rust)
     */ safeUnwrap ( ) { return this . val ; } toString ( ) { return `Ok(${ toString ( this . val ) })` ; } } export const Ok = OkImpl as typeof OkImpl & ( < T > ( val : T ) => Ok < T > ) ; export type Ok < T > = OkImpl < T > ; export type Result < T , E > = Ok < T > | Err < E > ; export type ResultOkType < T extends Result < any , any > > = T extends Ok < infer U > ? U : never ; export type ResultErrType < T > = T extends Err < infer U > ? U : never ; export type ResultOkTypes < T extends Result < any , any > [ ] > = { [ key in keyof T ] : T [ key ] extends Result < infer U , any > ? ResultOkType < T [ key ] > : never ; } ; export type ResultErrTypes < T extends Result < any , any > [ ] > = { [ key in keyof T ] : T [ key ] extends Result < infer U , any > ? ResultErrType < T [ key ] > : never ; } ; export namespace Result { /**
     * Parse a set of `Result`s, returning an array of all `Ok` values.
     * Short circuits with the first `Err` found, if any
     */ export function all < T extends Result < any , any > [ ] > ( ... results ) { const okResult = [ ] ; for ( let result of results ) { if ( result . ok ) { okResult . push ( result . val ) ; } else { return result as Err < ResultErrTypes < T > [ number ] > ; } } return new Ok ( okResult as ResultOkTypes < T > ) ; } /**
     * Parse a set of `Result`s, short-circuits when an input value is `Ok`.
     * If no `Ok` is found, returns an `Err` containing the collected error values
     */ export function any < T extends Result < any , any > [ ] > ( ... results ) { const errResult = [ ] ; for ( const result of results ) { if ( result . ok ) { return result as Ok < ResultOkTypes < T > [ number ] > ; } else { errResult . push ( result . val ) ; } } return new Err ( errResult as ResultErrTypes < T > ) ; } param op export function wrap < T , E = unknown > ( op ) { try { return new Ok ( op ( ) ) ; } catch ( e ) { return new Err < E > ( e ) ; } } param op export function wrapAsync < T , E = unknown > ( op ) { try { return op ( ) . then ( ( val ) => new Ok ( val ) ) . catch ( ( e ) => new Err ( e ) ) ; } catch ( e ) { return Promise . resolve ( new Err ( e ) ) ; } } export function isResult < T = any , E = any > ( val ) { return val instanceof Err || val instanceof Ok ; } }