import type { SafeParseReturnType, ZodType, ZodTypeDef } from 'zod';
import { ZodError, z } from 'zod';
type Val = NonNullable<unknown>;
type Nullable<T extends Val> = T | null | undefined;
interface Ok<T extends Val> {
    readonly ok: true;
    readonly val: T;
    readonly err?: never;
}
interface Err<E extends Val> {
    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<T extends Val, E extends Val> = Ok<T> | Err<E>;
/**
 * 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<T extends Val> = Exclude<T, SafeParseReturnType<unknown, T> | Promise<unknown>>;
/**
 * 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
 */
export declare class Result<T extends Val, E extends Val = Error> {
    private readonly res;
    private constructor();
    static ok<T extends Val>(val: T): Result<T, never>;
    static err<E extends Val>(err: E): Result<never, E>;
    static _uncaught<E extends Val>(err: E): Result<never, E>;
    /**
     * 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<Result<T, E>>` 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<T extends Val, Input = unknown>(zodResult: SafeParseReturnType<Input, T>): Result<T, ZodError<Input>>;
    static wrap<T extends Val, E extends Val = Error>(callback: () => RawValue<T>): Result<T, E>;
    static wrap<T extends Val, E extends Val = Error, EE extends Val = never>(promise: Promise<Result<T, EE>>): AsyncResult<T, E | EE>;
    static wrap<T extends Val, E extends Val = Error>(promise: Promise<RawValue<T>>): AsyncResult<T, E>;
    /**
     * 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<T extends Val, E extends Val = Error, ErrForNullable extends Val = Error>(callback: () => Nullable<T>, errForNullable: ErrForNullable): Result<T, E | ErrForNullable>;
    static wrapNullable<T extends Val, E extends Val = Error, ErrForNull extends Val = Error, ErrForUndefined extends Val = Error>(callback: () => Nullable<T>, errForNull: ErrForNull, errForUndefined: ErrForUndefined): Result<T, E | ErrForNull | ErrForUndefined>;
    static wrapNullable<T extends Val, E extends Val = Error, ErrForNullable extends Val = Error>(promise: Promise<Nullable<T>>, errForNullable: ErrForNullable): AsyncResult<T, E | ErrForNullable>;
    static wrapNullable<T extends Val, E extends Val = Error, ErrForNull extends Val = Error, ErrForUndefined extends Val = Error>(promise: Promise<Nullable<T>>, errForNull: ErrForNull, errForUndefined: ErrForUndefined): AsyncResult<T, E | ErrForNull | ErrForUndefined>;
    static wrapNullable<T extends Val, E extends Val = Error, ErrForNullable extends Val = Error>(value: Nullable<T>, errForNullable: ErrForNullable): Result<T, E | ErrForNullable>;
    static wrapNullable<T extends Val, E extends Val = Error, ErrForNull extends Val = Error, ErrForUndefined extends Val = Error>(value: Nullable<T>, errForNull: ErrForNull, errForUndefined: ErrForUndefined): Result<T, E | ErrForNull | ErrForUndefined>;
    /**
     * 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<T, E>;
    /**
     * 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').unwrapOrElse('foo');
     *   expect(val).toBe('foo');
     *
     *   ```
     */
    unwrapOrElse(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<U extends Val, EE extends Val>(fn: (value: T) => Result<U, E | EE>): Result<U, E | EE>;
    transform<U extends Val, EE extends Val>(fn: (value: T) => AsyncResult<U, E | EE>): AsyncResult<U, E | EE>;
    transform<U extends Val, Input = unknown>(fn: (value: T) => SafeParseReturnType<Input, NonNullable<U>>): Result<U, E | ZodError<Input>>;
    transform<U extends Val, Input = unknown>(fn: (value: T) => Promise<SafeParseReturnType<Input, NonNullable<U>>>): AsyncResult<U, E | ZodError<Input>>;
    transform<U extends Val, EE extends Val>(fn: (value: T) => Promise<Result<U, E | EE>>): AsyncResult<U, E | EE>;
    transform<U extends Val>(fn: (value: T) => Promise<RawValue<U>>): AsyncResult<U, E>;
    transform<U extends Val>(fn: (value: T) => RawValue<U>): Result<U, E>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: E) => Result<U, E | EE>): Result<T | U, E | EE>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: E) => AsyncResult<U, E | EE>): AsyncResult<T | U, E | EE>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: E) => Promise<Result<U, E | EE>>): AsyncResult<T | U, E | EE>;
    /**
     * 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<T, Schema extends ZodType<T, ZodTypeDef, Input>, Input = unknown>(input: unknown, schema: Schema): Result<NonNullable<z.infer<Schema>>, ZodError<Input>>;
    /**
     * Given a `schema`, returns a `Result` with `val` being the parsed value.
     * Additionally, `null` and `undefined` values are converted into Zod error.
     */
    parse<T, Schema extends ZodType<T, ZodTypeDef, Input>, Input = unknown>(schema: Schema): Result<NonNullable<z.infer<Schema>>, E | ZodError<Input>>;
    /**
     * Call `fn` on the `val` if the result is ok.
     */
    onValue(fn: (value: T) => void): Result<T, E>;
    /**
     * Call `fn` on the `err` if the result is err.
     */
    onError(fn: (err: E) => void): Result<T, E>;
}
/**
 * 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.
 */
export declare class AsyncResult<T extends Val, E extends Val> implements PromiseLike<Result<T, E>> {
    private asyncResult;
    private constructor();
    then<TResult1 = Result<T, E>>(onfulfilled?: ((value: Result<T, E>) => TResult1 | PromiseLike<TResult1>) | undefined | null): PromiseLike<TResult1>;
    static ok<T extends Val>(val: T): AsyncResult<T, never>;
    static err<E extends Val>(err: NonNullable<E>): AsyncResult<never, E>;
    static wrap<T extends Val, E extends Val = Error, EE extends Val = never, Input = unknown>(promise: Promise<SafeParseReturnType<Input, T>> | Promise<Result<T, EE>> | Promise<RawValue<T>>, onErr?: (err: NonNullable<E>) => Result<T, E>): AsyncResult<T, E | EE>;
    static wrapNullable<T extends Val, E extends Val, ErrForNull extends Val, ErrForUndefined extends Val>(promise: Promise<Nullable<T>>, errForNull: NonNullable<ErrForNull>, errForUndefined: NonNullable<ErrForUndefined>): AsyncResult<T, E | ErrForNull | ErrForUndefined>;
    /**
     * 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<Res<T, E>>;
    /**
     * Returns a success value or a fallback value.
     *
     *   ```ts
     *
     *   const val = await Result.wrap(readFile('foo.txt')).unwrapOrElse('bar');
     *   expect(val).toBe('bar');
     *   expect(err).toBeUndefined();
     *
     *   ```
     */
    unwrapOrElse(fallback: T): Promise<T>;
    /**
     * Returns the ok-value or throw the error.
     */
    unwrapOrThrow(): Promise<T>;
    /**
     * Returns the ok-value or `null`.
     */
    unwrapOrNull(): Promise<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
     *
     *   const { val, err } = await Result.wrap(
     *     http.getJson('https://api.example.com/data.json')
     *   )
     *     .transform(({ body }) => body)
     *     .unwrap();
     *
     *   ```
     */
    transform<U extends Val, EE extends Val>(fn: (value: T) => Result<U, E | EE>): AsyncResult<U, E | EE>;
    transform<U extends Val, EE extends Val>(fn: (value: T) => AsyncResult<U, E | EE>): AsyncResult<U, E | EE>;
    transform<U extends Val, Input = unknown>(fn: (value: T) => SafeParseReturnType<Input, NonNullable<U>>): AsyncResult<U, E | ZodError<Input>>;
    transform<U extends Val, Input = unknown>(fn: (value: T) => Promise<SafeParseReturnType<Input, NonNullable<U>>>): AsyncResult<U, E | ZodError<Input>>;
    transform<U extends Val, EE extends Val>(fn: (value: T) => Promise<Result<U, E | EE>>): AsyncResult<U, E | EE>;
    transform<U extends Val>(fn: (value: T) => Promise<RawValue<U>>): AsyncResult<U, E>;
    transform<U extends Val>(fn: (value: T) => RawValue<U>): AsyncResult<U, E>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: NonNullable<E>) => Result<U, E | EE>): AsyncResult<T | U, E | EE>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: NonNullable<E>) => AsyncResult<U, E | EE>): AsyncResult<T | U, E | EE>;
    catch<U extends Val = T, EE extends Val = E>(fn: (err: NonNullable<E>) => Promise<Result<U, E | EE>>): AsyncResult<T | U, E | EE>;
    /**
     * Given a `schema`, returns a `Result` with `val` being the parsed value.
     * Additionally, `null` and `undefined` values are converted into Zod error.
     */
    parse<T, Schema extends ZodType<T, ZodTypeDef, Input>, Input = unknown>(schema: Schema): AsyncResult<NonNullable<z.infer<Schema>>, E | ZodError<Input>>;
    onValue(fn: (value: T) => void): AsyncResult<T, E>;
    onError(fn: (err: E) => void): AsyncResult<T, E>;
}
export {};
