UNPKG

ts-safe

Version:

A functional, type-safe utility library for elegant error handling and asynchronous operations in JavaScript/TypeScript.

182 lines (174 loc) 8.98 kB
type SafeResult<T = any> = { isOk: false; error: Error; value?: undefined; } | { isOk: true; error?: undefined; value: T; }; /** * Represents a safe container for values that handles errors gracefully * and supports both synchronous and asynchronous operations. */ interface Safe<T> { /** * Transforms the value inside the safe container. * If the container has an error, the transform is not applied. * * @param transform Function to transform the value * @returns A new Safe containing the transformed value */ map<U>(transform: (value: T extends PromiseLike<any> ? Awaited<T> : T) => U): U extends PromiseLike<any> ? Safe<U> : T extends PromiseLike<any> ? Safe<Promise<U>> : Safe<U>; /** * Transforms the value with a function that returns another Safe. * Used for flattening nested Safe containers. * * @param transform Function that returns another Safe * @returns A flattened Safe container */ flatMap<U>(transform: (value: T extends PromiseLike<any> ? Awaited<T> : T) => Safe<U>): U extends PromiseLike<any> ? Safe<U> : T extends PromiseLike<any> ? Safe<Promise<U>> : Safe<U>; /** * Observes the current state without affecting it. * Provides access to both value and error information. * Any errors thrown inside this function are ignored. * * @param consumer Function to observe the current state * @returns The same Safe, preserving the original value */ watch(consumer: (result: T extends PromiseLike<any> ? SafeResult<Awaited<T>> : SafeResult<T>) => any): Safe<T>; /** * Applies a side effect to the value. * Errors thrown inside this function will propagate through the chain. * If the function returns a Promise, the chain becomes asynchronous. * * @param effectFn Function to apply a side effect * @returns The same Safe with possibly different promise state */ effect<U>(effectFn: (value: T extends PromiseLike<any> ? Awaited<T> : T) => U): T extends PromiseLike<any> ? Safe<T> : U extends PromiseLike<any> ? Safe<Promise<T>> : Safe<T>; /** * Recovers from an error by providing a fallback value. * If there's no error, the original value is kept. * * @param handler Function that returns a fallback value * @returns A Safe with either the original value or recovery value */ catch<U>(handler: (error: Error) => U): Safe<T extends PromiseLike<any> ? Promise<Awaited<T> | (U extends PromiseLike<any> ? Awaited<U> : U)> : T | U>; /** * Indicates if the Safe contains a success value. * Returns a Promise for asynchronous operations. */ isOk: T extends PromiseLike<any> ? Promise<boolean> : boolean; /** * Extracts the value from the Safe. * Throws if there's an error. * * @returns The value (or Promise<value> for async operations) * @throws The error if present */ unwrap(): T; /** * Extracts the value or returns a fallback if there's an error. * Never throws an exception. * * @param fallback The value to return if there's an error * @returns The success value or the fallback value */ orElse<U>(fallback: U): T extends PromiseLike<any> ? Promise<Awaited<T> | U> : T | U; } /** * Type for watch function parameters. */ type WatchFuncion<T = unknown> = Parameters<Safe<T>['watch']>[0]; type NonDistributive<T> = [T] extends [any] ? T : never; type HasPromise<T> = NonDistributive<T> extends Promise<any> ? true : (T extends any ? (T extends Promise<any> ? true : false) : never) extends false ? false : true; type SafeCheckPromise<T, U> = HasPromise<U> extends true ? Safe<Promise<Awaited<T>>> : Safe<T>; type SafeMap<A, B> = (input: A extends PromiseLike<any> ? Awaited<A> : A) => B; declare function safePipe<Input, A>(ab: SafeMap<Input, A>): (input: Input) => SafeCheckPromise<A, Input>; declare function safePipe<Input, A, B>(a: SafeMap<Input, A>, b: SafeMap<A, B>): (input: Input) => SafeCheckPromise<B, A | Input>; declare function safePipe<Input, A, B, C>(a: SafeMap<Input, A>, b: SafeMap<A, B>, c: SafeMap<B, C>): (input: Input) => SafeCheckPromise<C, A | B | Input>; declare function safePipe<Input, A, B, C, D>(a: SafeMap<Input, A>, b: SafeMap<A, B>, c: SafeMap<B, C>, d: SafeMap<C, D>): (input: Input) => SafeCheckPromise<D, A | B | C | Input>; declare function safePipe<Input, A, B, C, D, E>(a: SafeMap<Input, A>, b: SafeMap<A, B>, c: SafeMap<B, C>, d: SafeMap<C, D>, e: SafeMap<D, E>): (input: Input) => SafeCheckPromise<E, A | B | C | D | Input>; declare function safePipe<Input, A, B, C, D, E, F>(a: SafeMap<Input, A>, b: SafeMap<A, B>, c: SafeMap<B, C>, d: SafeMap<C, D>, e: SafeMap<D, E>, f: SafeMap<E, F>): (input: Input) => SafeCheckPromise<F, A | B | C | D | E | Input>; declare function safePipe<Input, A, B, C, D, E, F, G>(a: SafeMap<Input, A>, b: SafeMap<A, B>, c: SafeMap<B, C>, d: SafeMap<C, D>, e: SafeMap<D, E>, f: SafeMap<E, F>, g: SafeMap<F, G>): (input: Input) => SafeCheckPromise<G, A | B | C | D | E | F | Input>; /** * Creates a validator function that throws an error if the value is null or undefined. * * @template T - The type of the value to validate * @param {string} [message='Value is null or undefined'] - The error message to throw * @returns {function(T): T} A function that validates input and returns it if valid * @throws {Error} If the value is null or undefined */ declare const errorIfNull: <T = unknown>(message?: string) => ((value: T) => T); /** * Creates a validator function that throws an error if the value is falsy. * Falsy values include: null, undefined, empty string, 0, false, NaN. * * @template T - The type of the value to validate * @param {string} [message='Value is falsy'] - The error message to throw * @returns {function(T): T} A function that validates input and returns it if valid * @throws {Error} If the value is falsy */ declare const errorIfFalsy: <T = unknown>(message?: string) => ((value: T) => T); /** * Creates a validator function that throws an error if the array or string is empty. * * @template T - The type of the value to validate (must have a length property) * @param {string} [message='Value is empty'] - The error message to throw * @returns {function(T): T} A function that validates input and returns it if valid * @throws {Error} If the value has a length of 0 */ declare const errorIfEmpty: <T extends { length: number; }>(message?: string) => ((value: T) => T); /** * Creates a validator function that throws an error based on a custom condition. * * @template T - The type of the value to validate * @param {function(T): (string|false|undefined)} check - Function that should return an error message * if validation fails, or false/undefined if validation passes * @returns {function(T): T} A function that validates input and returns it if valid * @throws {Error} If the check function returns a string (error message) */ declare const errorIf: <T>(check: (value: T) => string | false | undefined) => ((value: T) => T); /** * Creates a function that observes and processes errors in a SafeResult. * This utility only calls the consumer function when the result contains an error. * * @param {function(Error): any} consumer - Function to process the error * @returns {function(SafeResult): void} A function that calls the consumer only if the result has an error */ declare const watchError: (consumer: (error: Error) => any) => (result: SafeResult) => void; /** * Creates a function that observes and processes success values in a SafeResult. * This utility only calls the consumer function when the result contains a success value. * * @template T - The type of the success value * @param {function(T): any} consumer - Function to process the success value * @returns {function(SafeResult<T>): void} A function that calls the consumer only if the result has a success value */ declare const watchOk: <T>(consumer: (value: T) => any) => (result: SafeResult<T>) => void; /** * Creates a function that will automatically retry a failed operation * @param fn The function to retry * @param options Configuration options for retry behavior * @returns A wrapped function that implements retry logic */ declare const retry: <T, U>(fn: (arg: T) => Promise<U> | U, options?: { maxTries?: number; delay?: number; backoff?: boolean; }) => (arg: T) => Promise<U>; /** * * @param init Optional value or function that returns a value * @returns A Safe containing the value or function result */ declare function safe<T>(init: () => T): Safe<T>; declare function safe<T>(init: T): Safe<T>; declare function safe(): Safe<undefined>; declare namespace safe { var pipe: typeof safePipe; } declare const s: typeof safe; export { type Safe, type SafeResult, type WatchFuncion, errorIf, errorIfEmpty, errorIfFalsy, errorIfNull, retry, s, safe, safePipe, watchError, watchOk };