interface FulfilledResult { status: "fulfilled"; value: T; } interface RejectedResult { status: "rejected"; reason: unknown; } type SafeReturn = TOut extends Promise ? Promise> | RejectedResult> : FulfilledResult> | RejectedResult; export const safeFn = (fn: (...args: TArgs[]) => TOut) => (...args: TArgs[]): SafeReturn => { try { const maybePromise = fn(...args); if (maybePromise instanceof Promise) { return maybePromise .catch((error) => ({ status: "rejected", reason: error, })) .then((result) => ({ status: "fulfilled", value: result, })) as SafeReturn; } return { status: "fulfilled", value: maybePromise, } as SafeReturn; } catch (error) { return { status: "rejected", reason: error, } as SafeReturn; } };