import { Nullish } from "../types/index.js"; import { SafeParseReturnType, ZodError, ZodType, input, output } from "zod/v3"; //#region lib/util/result.d.ts type Val = NonNullable; interface Ok { readonly ok: true; readonly val: T; readonly err?: never; } interface Err { readonly ok: false; readonly err: E; readonly val?: never; /** * Internal flag to indicate that the error was thrown during `.transform()` * and will be re-thrown on `.unwrap()`. */ readonly _uncaught?: true; } type Res = Ok | Err; /** * All non-nullable values that also are not Promises nor Zod results. * It's useful for restricting Zod results to not return `null` or `undefined`. */ type RawValue = Exclude | Promise>; /** * Class for representing a result that can fail. * * The mental model: * - `.wrap()` and `.wrapNullable()` are sinks * - `.transform()` are pipes which can be chained * - `.unwrap()` is the point of consumption */ declare class Result { private readonly res; private constructor(); static ok(val: T): Result; static err(err: E): Result; static _uncaught(err: E): Result; /** * Wrap a callback or promise in a Result in such a way that any thrown errors * are caught and wrapped with `Result.err()` (and hence never re-thrown). * * In case of a promise, the `AsyncResult` is returned. * Use `.unwrap()` to get the `Promise>` from `AsyncResult`. * * ```ts * * // SYNC * const parse = (json: string) => Result.wrap(() => JSON.parse(json)); * * const { val, err } = parse('{"foo": "bar"}').unwrap(); * expect(val).toEqual({ foo: 'bar' }); * expect(err).toBeUndefined(); * * const { val, err } = parse('!!!').unwrap(); * expect(val).toBeUndefined(); * expect(err).toBeInstanceOf(SyntaxError); * * // ASYNC * const request = (url: string) => Result.wrap(http.get(url)); * * const { val, err } = await request('https://example.com').unwrap(); * expect(val).toBeString(); * expect(err).toBeUndefined(); * * ``` */ static wrap(zodResult: SafeParseReturnType): Result>; static wrap(callback: () => RawValue): Result; static wrap(callback: () => Promise>): AsyncResult; static wrap(promise: Promise>): AsyncResult; static wrap(promise: Promise>): AsyncResult; /** * Similar to `Result.wrap()`, but helps to undo the billion dollar mistake by * replacing `null` or `undefined` with an error of provided type. * * Errors thrown inside the callback or promise are caught and wrapped with `Result.err()`, * hence never re-thrown. * * Since functions and promises returning nullable can't be wrapped with `Result.wrap()` * because `val` is constrained by being `NonNullable`, `null` and `undefined` * must be converted to some sort of `err` value. * * This method does exactly this, i.g. it is the feature-rich shorthand for: * * ```ts * const { val, err } = Result.wrap(() => { * const result = callback(); * return result === null || result === undefined * ? Result.err('oops') * : Result.ok(result); * }).unwrap(); * ``` * * In case of a promise, the `AsyncResult` is returned. * * ```ts * * // SYNC * const getHostname = (url: string) => * Result.wrapNullable( * () => parseUrl(url)?.hostname, * 'invalid-url' as const * ); * const { val, err } = getHostname('foobar').unwrap(); * expect(val).toBeUndefined(); * expect(err).toBe('invalid-url'); * * // ASYNC * const { val, err } = await Result.wrapNullable( * readLocalFile('yarn.lock'), * 'file-read-error' as const * ).unwrap(); * * ``` */ static wrapNullable(callback: () => Nullish, errForNullable: ErrForNullable): Result; static wrapNullable(callback: () => Nullish, errForNull: ErrForNull, errForUndefined: ErrForUndefined): Result; static wrapNullable(promise: Promise>, errForNullable: ErrForNullable): AsyncResult; static wrapNullable(promise: Promise>, errForNull: ErrForNull, errForUndefined: ErrForUndefined): AsyncResult; static wrapNullable(value: Nullish, errForNullable: ErrForNullable): Result; static wrapNullable(value: Nullish, errForNull: ErrForNull, errForUndefined: ErrForUndefined): Result; /** * Returns a discriminated union for type-safe consumption of the result. * When error was uncaught during transformation, it's being re-thrown here. * * ```ts * * const { val, err } = Result.ok('foo').unwrap(); * expect(val).toBe('foo'); * expect(err).toBeUndefined(); * * ``` */ unwrap(): Res; /** * Returns a success value or a fallback value. * When error was uncaught during transformation, it's being re-thrown here. * * ```ts * * const value = Result.err('bar').unwrapOr('foo'); * expect(val).toBe('foo'); * * ``` */ unwrapOr(fallback: T): T; /** * Returns the ok-value or throw the error. */ unwrapOrThrow(): T; /** * Returns the ok-value or `null`. * When error was uncaught during transformation, it's being re-thrown here. */ unwrapOrNull(): T | null; /** * Transforms the ok-value, sync or async way. * * Transform functions SHOULD NOT throw. * Uncaught errors are logged and wrapped to `Result._uncaught()`, * which leads to re-throwing them in `unwrap()`. * * Zod `.safeParse()` results are converted automatically. * * ```ts * * // SYNC * const { val, err } = Result.ok('foo') * .transform((x) => x.length) * .unwrap(); * expect(val).toBe(3); * * // ASYNC * const { val, err } = await Result.wrap( * http.getJson('https://api.example.com/data.json') * ) * .transform(({ body }) => body) * .unwrap(); * * ``` */ transform(fn: (value: T) => Result): Result; transform(fn: (value: T) => AsyncResult): AsyncResult; transform(fn: (value: T) => SafeParseReturnType>): Result>; transform(fn: (value: T) => Promise>>): AsyncResult>; transform(fn: (value: T) => Promise>): AsyncResult; transform(fn: (value: T) => Promise>): AsyncResult; transform(fn: (value: T) => RawValue): Result; catch(fn: (err: E) => Result): Result; catch(fn: (err: E) => AsyncResult): AsyncResult; catch(fn: (err: E) => Promise>): AsyncResult; /** * Given a `schema` and `input`, returns a `Result` with `val` being the parsed value. * Additionally, `null` and `undefined` values are converted into Zod error. */ static parse>(input: unknown, schema: Schema): Result>, ZodError>>; /** * Given a `schema`, returns a `Result` with `val` being the parsed value. * Additionally, `null` and `undefined` values are converted into Zod error. */ parse>(schema: Schema): Result>, E | ZodError>>; /** * Call `fn` on the `val` if the result is ok. */ onValue(fn: (value: T) => void): Result; /** * Call `fn` on the `err` if the result is err. */ onError(fn: (err: E) => void): Result; } /** * This class is being used when `Result` methods encounter async code. * It isn't meant to be used directly, but exported for usage in type annotations. * * All the methods resemble `Result` methods, but work asynchronously. */ declare class AsyncResult implements PromiseLike> { private asyncResult; private constructor(); then>(onfulfilled?: ((value: Result) => TResult1 | PromiseLike) | null): PromiseLike; static ok(val: T): AsyncResult; static err(err: NonNullable): AsyncResult; static wrap(promise: Promise> | Promise> | Promise>, onErr?: (err: NonNullable) => Result): AsyncResult; static wrapNullable(promise: Promise>, errForNull: NonNullable, errForUndefined: NonNullable): AsyncResult; /** * Returns a discriminated union for type-safe consumption of the result. * * ```ts * * const { val, err } = await Result.wrap(readFile('foo.txt')).unwrap(); * expect(val).toBe('foo'); * expect(err).toBeUndefined(); * * ``` */ unwrap(): Promise>; /** * Returns a success value or a fallback value. * * ```ts * * const val = await Result.wrap(readFile('foo.txt')).unwrapOr('bar'); * expect(val).toBe('bar'); * expect(err).toBeUndefined(); * * ``` */ unwrapOr(fallback: T): Promise; /** * Returns the ok-value or throw the error. */ unwrapOrThrow(): Promise; /** * Returns the ok-value or `null`. */ unwrapOrNull(): Promise; /** * Transforms the ok-value, sync or async way. * * Transform functions SHOULD NOT throw. * Uncaught errors are logged and wrapped to `Result._uncaught()`, * which leads to re-throwing them in `unwrap()`. * * Zod `.safeParse()` results are converted automatically. * * ```ts * * const { val, err } = await Result.wrap( * http.getJson('https://api.example.com/data.json') * ) * .transform(({ body }) => body) * .unwrap(); * * ``` */ transform(fn: (value: T) => Result): AsyncResult; transform(fn: (value: T) => AsyncResult): AsyncResult; transform(fn: (value: T) => SafeParseReturnType>): AsyncResult>; transform(fn: (value: T) => Promise>>): AsyncResult>; transform(fn: (value: T) => Promise>): AsyncResult; transform(fn: (value: T) => Promise>): AsyncResult; transform(fn: (value: T) => RawValue): AsyncResult; catch(fn: (err: NonNullable) => Result): AsyncResult; catch(fn: (err: NonNullable) => AsyncResult): AsyncResult; catch(fn: (err: NonNullable) => Promise>): AsyncResult; /** * Given a `schema`, returns a `Result` with `val` being the parsed value. * Additionally, `null` and `undefined` values are converted into Zod error. */ parse>(schema: Schema): AsyncResult>, E | ZodError>>; onValue(fn: (value: T) => void): AsyncResult; onError(fn: (err: E) => void): AsyncResult; } //#endregion export { AsyncResult }; //# sourceMappingURL=result.d.ts.map