UNPKG

tiinvo

Version:

A library of types and utilities for your TypeScript and JavaScript projects

250 lines (249 loc) 5.62 kB
import { make as makecatch } from './Catch.js'; import { catchableAsync, catchableSync } from './Functors.js'; /** * Returns an `Err` * * @example * * ```ts * import { Result } from 'tiinvo'; * * Result.err(10) instanceof Error // true * Result.err(new TypeError('aaaa')) instanceof Error // true * Result.err({}) instanceof Error // true * Result.err(10n) instanceof Error // true * Result.err([10, 20, 30]) instanceof Error // true * ``` * * @param a * @returns * @group Factories * @since 3.8.0 */ export const err = (a) => { if (a instanceof Error) { return a; } else if (typeof a === 'object' && a) { const err = new Error(); for (const [key, value] of Object.entries(a)) { err[key] = value; } return err; } return new Error(String(a)); }; //#region guards /** * Checks if a value is `Err` * * @example * * ```ts * import { Result } from 'tiinvo'; * * Result.isErr(10) // false * Result.isErr(new TypeError('aaaa')) // true * ``` * * @param x the value to check * @returns true if `x` is `Err`, false otherwise * @group Guardables * @since 4.0.0 */ export const isErr = (x) => x instanceof Error || (typeof x === 'object' && x !== null && 'message' in x && 'name' in x && 'cause' in x); /** * Checks if a value is `Ok` * * @example * * ```ts * import { Result } from 'tiinvo'; * * Result.isOk(10) // true * Result.isOk(new TypeError('aaaa')) // false * ``` * * @param x * @returns true if `x` is `Ok<A>`, false otherwise * @group Guardables * @since 4.0.0 */ export const isOk = (x) => !isErr(x); /** * Checks if a value is `Ok<A>` * * ```ts * import { Num, Result } from 'tiinvo'; * * const guard = Result.isOkOf(Num.guard); * * guard(10) // true * guard("hello") // false * guard(new TypeError('aaaa')) // false * ``` * * @template A the type * @param g the type guard * @returns the Guard * @group Guardables * @since 4.0.0 */ export const isOkOf = (g) => (x) => isErr(x) ? false : g(x); export function cmp(cmp, a, b) { const _cmp = (x, y) => { if (isErr(x) && isErr(y)) { return 0; } if (isErr(x)) { return -1; } if (isErr(y)) { return 1; } return typeof cmp === 'function' ? cmp(x, y) : cmp.cmp(x, y); }; switch (arguments.length) { case 3: return _cmp(a, b); case 2: return (b) => _cmp(b, a); case 1: return (a, b) => _cmp(a, b); } } ; export function eq(eq, a, b) { const _eq = (x, y) => { if (isErr(x) && isErr(y)) { return true; } if (isErr(x) || isErr(y)) { return false; } return typeof eq === 'function' ? eq(x, y) : eq.eq(x, y); }; switch (arguments.length) { case 3: return _eq(a, b); case 2: return (b) => _eq(a, b); case 1: return (a, b) => _eq(a, b); } } ; export function filter(f, a) { const _err = Error("Value did not pass filter"); if (arguments.length === 2) { return isErr(a) ? _err : f(a) ? a : _err; } return (c) => isErr(c) ? _err : f(c) ? c : _err; } //#endregion //#region mappables /** * Maps `Result.t<a>` to `Result.t<b>` if ok, otherwise returns `err` * * ```ts * import { Num, Result } from 'tiinvo'; * * const m = Result.map(Num.add(10)) * * m(10) // 20 * m(new Error('foobar!')) // Error('foobar!') * ``` * * @param m the Mappable functor * @returns * @since 4.0.0 */ export const map = (m) => (a) => isOk(a) ? m(a) : a; /** * Maps `Result.t<a>` to `Result.t<b>` if ok, otherwise returns `b` * * ```ts * import { Str, Result } from 'tiinvo'; * * const map = Result.mapOr(Str.length, 0); * * map('hello') // 5 * map(new Error()) // 0 * ``` * * @param value * @returns * @since 4.0.0 */ export const mapOr = (m, b) => (a) => isOk(a) ? m(a) : b; //#endregion //#region catchables /** * Calls a function `f` with it's arguments and returns a `Promise<Result.t<ReturnType<f>>>` * * ```typescript * import { Result, Num } from 'tiinvo'; * * const fn = async (arg: number) => { * if (Num.isEven(arg)) { * return arg * 2; * } * * throw new Error(`${arg} is not even`); * } * * const safe = Result.tryAsync(fn); * * await safe(2) // 4 * await safe(3) // Error("3 is not even") * * Result.isOk(await safe(2)) // true * Result.isErr(await safe(3)) // true * ``` * * @param fn * @returns * @since 4.0.0 */ export const tryAsync = (f) => { return makecatch({ [catchableAsync]() { return { catch: async (error) => error, func: f }; } }); }; /** * Calls a function `f` with it's arguments and returns a `Promise<Result.t<ReturnType<f>>>` * * ```typescript * import { Result, Num } from 'tiinvo'; * * const fn = (arg: number) => { * if (Num.isEven(arg)) { * return arg * 2; * } * * throw new Error(`${arg} is not even`); * } * * const safe = Result.trySync(fn); * * safe(2) // 4 * safe(3) // Error("3 is not even") * * Result.isOk(safe(2)) // true * Result.isErr(safe(3)) // true * ``` * * @param fn * @returns * @since 4.0.0 */ export const trySync = (f) => { return makecatch({ [catchableSync]() { return { catch: (error) => error, func: f }; } }); }; //#endregion