import { isPromise, resolveDefault } from './internals.js' /** * Result type with Error and a default value. * On error, returns [Error, DefaultT] * On success, returns [undefined, T] */ export type ResultWithDefault = readonly [E, D] | readonly [undefined, T] /** * Executes a function, promise, or value and returns a Result type with a fallback default. * If an error occurs, it returns the actual Error object and the default value. * * @template T The type of the successful result * @template D The type of the default value (defaults to T) * @param {T | Promise | (() => T | Promise)} value - The value, promise, or function to execute * @param {D | (() => D)} defaultValue - The default value or a function to compute it (only called on failure) * @returns {ResultWithDefault | Promise>} A tuple of [error, value] or Promise thereof * * @example * // With a static default * const [err, config] = goElse(() => JSON.parse('invalid'), { port: 3000 }) * // err is the Error object, config is { port: 3000 } * * @example * // With a computed default (lazy evaluation) * const [err, user] = await goElse(fetchUser(id), () => ({ * id: 'anonymous', * name: 'Guest' * })) */ export function goElse( fn: () => never, defaultValue: D | (() => D), ): ResultWithDefault export function goElse( fn: () => Promise, defaultValue: D | (() => D), ): Promise> export function goElse( promise: Promise, defaultValue: D | (() => D), ): Promise> export function goElse( fn: () => T, defaultValue: D | (() => D), ): ResultWithDefault export function goElse( value: T, defaultValue: D | (() => D), ): ResultWithDefault export function goElse( value: T | Promise | (() => T | Promise), defaultValue: D | (() => D), ): ResultWithDefault | Promise> { try { const result = typeof value === 'function' ? (value as () => T | Promise)() : value if (isPromise(result)) { return result .then((resolvedValue): ResultWithDefault => [undefined, resolvedValue]) .catch((err): ResultWithDefault => { const error = err instanceof Error ? err : new Error(String(err)) return [error, resolveDefault(defaultValue)] }) } return [undefined, result] } catch (err) { const error = err instanceof Error ? err : new Error(String(err)) return [error, resolveDefault(defaultValue)] } }