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(impl: any) { return (this[1] as Status).Of(impl); } } type Unwrap = 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>; };