@zodyac/safe-wrap
v0.1.0
Published
Type-safe Result wrapping for sync & async code — wrap/unwrap, combinators, retry and timeout, no exceptions
Maintainers
Readme
@zodyac/safe-wrap
Type-safe Result wrapping for sync & async TypeScript — turn throwing code into
a discriminated { result, error } union, with combinators, retry and timeout.
No exceptions to forget, no any from a catch.
npm i @zodyac/safe-wrapWhy
try/catch loses the error type (catch (e) is unknown) and lets failures
escape silently. safe-wrap makes the failure a value you must handle:
import { wrapAsync } from '@zodyac/safe-wrap';
const { result, error } = await wrapAsync(() => fetch('/api').then((r) => r.json()));
if (error) return handle(error); // error: Error, narrowed
use(result); // result: non-null, narrowedAPI
Wrap — run code, capture throw as a value:
wrapSync(fn)/wrapAsync(fn)→iWrapped<T>={ result: T, error: null } | { result: null, error: Err }.wrapResult(value)/wrapError(err)— construct a wrapped value directly.unwrapResult(wrapped)— throw the error or return the result (escape hatch).
Status — for void/side-effecting calls where you only care if it failed:
wrapStatus(fn)/wrapAsyncStatus(fn)→iWrappedStatus={ result: 'success', error: null } | { result: 'error', error: Err }.success/wrapSuccess()/wrapErrorStatus(err)/unwrapStatus(s).
Combine — chain without unwrapping:
andThen(wrapped, fn)/andThenAsync(wrapped, fn)— map the success branch, short-circuit on error.
Retry & timeout:
wrapRetry(fn, opts)/wrapRetryIf(fn, predicate, opts)/retryDelay(...).withTimeout(promise, ms)— rejects withTimeoutErrorpast the deadline.
Types: iWrapped, iWrappedResult, iWrappedError, iWrappedStatus, iWrappedSuccess, iWrappedErrorStatus.
Develop
bun install
bun run build # tsup → dist (esm + cjs + d.ts)
bun run test # vitest
bun run lint # biome
bun run typecheck # tsc --noEmitLicense
MIT
