Eric Bower
·
2025-06-06
safe.ts
1import type { Callable, Operation, Result } from "effection";
2import { Err, Ok, call } from "effection";
3
4/**
5 * The goal of `safe` is to wrap Operations to prevent them from raising
6 * and error. The result of `safe` is always a {@link Result} type.
7 *
8 * @example
9 * ```ts
10 * import { safe } from "starfx";
11 *
12 * function* run() {
13 * const results = yield* safe(fetch("api.com"));
14 * if (result.ok) {
15 * console.log(result.value);
16 * } else {
17 * console.error(result.error);
18 * }
19 * }
20 * ```
21 */
22function isError(error: unknown): error is Error {
23 return error instanceof Error;
24}
25
26export function* safe<T>(operator: Callable<T>): Operation<Result<T>> {
27 try {
28 const value = yield* call<T>(operator as any);
29 return Ok(value);
30 } catch (error) {
31 return Err(isError(error) ? error : new Error(String(error)));
32 }
33}