/** * Extract the value or throw if it's an error. * * @example * const user = unwrap(result) // throws if result is an error * console.log(user.name) * * @example With custom message * const user = unwrap(result, 'Failed to get user') */ export function unwrap(value: V, message?: string): Exclude { if (value instanceof Error) { throw new Error(message ?? `Unwrap called on error: ${value.message}`, { cause: value, }) } return value as Exclude } /** * Extract the value or return a fallback if it's an error. * * @example * const name = unwrapOr(result, 'Anonymous') * // If result is User, returns user * // If result is Error, returns 'Anonymous' */ export function unwrapOr(value: V, fallback: U): Exclude | U { if (value instanceof Error) { return fallback } return value as Exclude } /** * Pattern match on an errore value. * Handles both success and error cases. * * @example * const message = match(result, { * ok: user => `Hello, ${user.name}`, * err: error => `Failed: ${error.message}` * }) */ export function match( value: V, handlers: { ok: (v: Exclude) => R err: (e: Extract) => R }, ): R { if (value instanceof Error) { return handlers.err(value as Extract) } return handlers.ok(value as Exclude) } /** * Partition an array of errore values into [successes, errors]. * * @example * const results = await Promise.all(ids.map(fetchUser)) * const [users, errors] = partition(results) */ export function partition( values: V[], ): [Exclude[], Extract[]] { const oks: Exclude[] = [] const errs: Extract[] = [] for (const v of values) { if (v instanceof Error) { errs.push(v as Extract) } else { oks.push(v as Exclude) } } return [oks, errs] } /** * Flatten a nested errore: (E1 | (E2 | T)) becomes (E1 | E2 | T). * Useful when chaining operations that can fail. * * @example * const nested: NetworkError | (ParseError | User) = await fetchAndParse() * const flat: NetworkError | ParseError | User = flatten(nested) */ export function flatten(value: V): V { return value }