import { Err, None, Ok, Option, PromisedResult, Result, ResultLike, ResultMapOption, ResultMapOrElse, ResultMapResult, ResultPromise, ResultPromiseLike, ResultValue, Some, UnwrapableResult, } from "./mod"; const ResultType = { Ok: Symbol(":ok"), Err: Symbol(":err"), }; export class OkValue implements UnwrapableResult { okValue: T; constructor(okValue: T) { this.okValue = okValue; } static from(ok: T): UnwrapableResult { return new OkValue(ok); } [Symbol.iterator](): IterableIterator { return [this.okValue][Symbol.iterator](); } get type(): symbol { return ResultType.Ok; } and(res: Result): Result { return res; } andThen(op: (value: T) => ResultPromiseLike): ResultPromise; andThen(op: (value: T) => Result): Result; andThen(op: (value: T) => ResultLike): ResultLike { return Ok(op(this.okValue)); } err(): Option { return None(); } isOk(): boolean { return true; } isErr(): boolean { return false; } /** * Maps an Result to Result by applying a function to a contained value. */ map(fn: (value: T) => Promise): PromisedResult; map(fn: (value: T) => U): Result; map( fn: (value: T) => U | Promise, ): Result | PromisedResult { return Ok(fn(this.okValue)) as Result; } mapErr(fn: (err: E) => Promise): ResultPromise; mapErr(fn: (err: E) => F): Result; mapErr( _: (err: E) => Result | Promise>, ): Result | ResultPromise { return Ok(this.okValue) as Result; } mapResult( _: (err: E) => U, fn: (ok: T) => U, ): ResultMapResult { return Ok(fn(this.okValue)) as ResultMapResult; } mapOption( _: (err: E) => U, fn: (value: T) => U, ): ResultMapOption { const rv = fn(this.okValue); return (rv instanceof Promise ? Some(rv) : rv) as ResultMapOption; } mapOrElse( _: (err: E) => U, fn: (value: T) => U, ): ResultMapOrElse { return fn(this.okValue) as ResultMapOrElse; } ok(): Option { return Some(this.okValue) as Option; } or(_: Result): Result { return ResultValue.from(this); } orElse(fn: (err: E) => Promise>): PromisedResult; orElse(fn: (err: E) => Result): Result; orElse( _: (err: E) => Result | Promise>, ): PromisedResult | Result { return ResultValue.from(this); } unwrap(): T { return this.okValue; } unwrapOr(_: T): T { return this.okValue; } unwrapOrElse(def: (err: E) => T): T; unwrapOrElse(def: (err: E) => Promise): T | Promise; unwrapOrElse(_: (err: E) => T | Promise): T { return this.okValue; } } export class ErrValue implements UnwrapableResult { constructor(private errValue: E) {} [Symbol.iterator](): IterableIterator { return [][Symbol.iterator](); } static from(err: E): Result { return new ErrValue(err); } and(_: Result): Result { return ResultValue.from(this as unknown as ErrValue); } andThen(fn: (_: T) => ResultPromiseLike): PromisedResult; andThen(fn: (_: T) => Result): Result; andThen(_: (_: T) => ResultLike): ResultLike { return Ok(this) as ResultLike; } err(): Option { return Some(this.errValue) as Option; } isOk(): boolean { return false; } isErr(): boolean { return true; } map(fn: (value: T) => Promise): PromisedResult; map(fn: (value: T) => U): Result; map( _: (value: T) => U | Promise, ): Result | PromisedResult { return ResultValue.from(this as unknown as ErrValue); } mapErr(fn: (err: E) => Promise): ResultPromise; mapErr(fn: (err: E) => F): Result; mapErr( fn: (err: E) => F | Promise, ): Result | ResultPromise { return Err(fn(this.errValue)) as Result; } mapResult( def: (err: E) => U, _: (ok: T) => U, ): ResultMapResult { const rv = def(this.errValue); return (rv instanceof Promise ? Ok(rv) : rv) as ResultMapResult; } mapOption( def: (err: E) => U, _: (_: T) => U, ): ResultMapOption { const rv = def(this.errValue); return (rv instanceof Promise ? Some(rv) : rv) as ResultMapOption; } mapOrElse( def: (err: E) => U, _: (_: T) => U, ): ResultMapOrElse { return def(this.errValue) as ResultMapOrElse; } ok(): Option { return None(); } or(optb: Result): Result { return optb; } orElse(fn: (err: E) => Promise>): ResultPromise; orElse(fn: (err: E) => Result): Result; orElse( fn: (err: E) => Result | Promise>, ): ResultPromise | Result { const alt = fn(this.errValue); return alt instanceof Promise ? PromisedResult.from(alt) : alt; } unwrap(): T { throw new Error("Cannot unwrap None"); } unwrapOr(def: T): T { return def; } unwrapOrElse(def: (err: E) => T): T; unwrapOrElse(def: (err: E) => Promise): T | Promise; unwrapOrElse(def: (err: E) => Promise | T): T | Promise { return def(this.errValue); } get type(): symbol { return ResultType.Err; } }