interface Status { message?: string; cause?: any; Ok(): boolean; Fail(): boolean; Of(cls: any): boolean; } export class Err extends Error { Ok() { return false; } Fail() { return true; } Of(cls: any) { return this.cause instanceof cls || this instanceof cls; } static fromCatch(error: any) { const e = new Err(typeof error === "string" ? error : error.message); e.cause = error; e.stack = error.stack; return e; } } export class Ok { Ok() { return true; } Fail() { return false; } Of(cls: any) { return this instanceof cls; } toString() { return "Ok"; } } interface IResult { 0: T; 1: Status; value: T; status: Status; Of(cls: any): boolean; Ok(): boolean; Fail(): boolean; } class Result extends Array implements IResult { 0: T; 1: Status; constructor(result: T, status: Status) { super(2); this[0] = result; this[1] = status; } get value() { return this[0]; } get status() { return this[1]; } Ok() { return (this[1] as Status).Ok(); } Fail() { return (this[1] as Status).Fail(); } Of(cls: any) { return (this[1] as Status).Of(cls); } Iter() { const value = this.value; const that = this; if ( typeof value !== "object" && !( typeof (value as any)[Symbol.iterator] === "function" || typeof (value as any)[Symbol.asyncIterator] === "function" ) ) { return { async *[Symbol.asyncIterator]() { yield new Result(that.value, that.status) as SafeResult; }, *[Symbol.iterator]() { yield new Result(that.value, that.status) as SafeResult; }, }; } return { async *[Symbol.asyncIterator]() { yield* asyncIterator(value as AsyncGenerator); }, *[Symbol.iterator]() { yield* iterator(value as Generator); }, }; } } type Unwrap = T extends AsyncGenerator ? U : T extends Generator ? U : T extends Promise ? U : T extends (...args: any) => Promise ? U : T extends (...args: any) => infer U ? U : T; export type SafeResult = T extends Promise ? Promise>> : T extends () => Promise ? Promise>> : Result>; export function grip(action: T): SafeResult { if (action instanceof Promise) { return promise(action) as SafeResult; } try { const result = (action as any)(); if (result instanceof Promise) { return promise(result) as SafeResult; } return new Result(result, new Ok()) as SafeResult; } catch (err: any) { return new Result(null as any, Err.fromCatch(err)) as SafeResult; } } const promise = (result: Promise) => { return result .then((res) => new Result(res, new Ok())) .catch((err) => new Result(null, Err.fromCatch(err))) as Promise>; }; const iterator = function* (iter: Generator) { try { let data = iter.next(); while (!data.done) { yield new Result(data.value as T, new Ok()) as SafeResult; data = iter.next(); } } catch (e) { yield new Result(null as T, Err.fromCatch(e)) as SafeResult; } }; const asyncIterator = async function* (iter: AsyncGenerator) { try { let data = await iter.next(); while (!data.done) { yield new Result(data.value as T, new Ok()) as SafeResult; data = await iter.next(); } } catch (e) { yield new Result(null as T, Err.fromCatch(e)) as SafeResult; } };