interface Ok<T> {
    readonly ok: true;
    readonly val: NonNullable<T>;
    readonly err?: never;
}
interface Err<E> {
    readonly ok: false;
    readonly err: NonNullable<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, E> = Ok<T> | Err<E>;
/**
 * 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, E = Error> {
    private readonly res;
    private constructor();
    static ok<T>(val: NonNullable<T>): Result<T, never>;
    static err<E>(err: NonNullable<E>): Result<never, E>;
    static _uncaught<E>(err: NonNullable<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, E = Error>(callback: () => NonNullable<T>): Result<T, E>;
    static wrap<T, E = Error, EE = never>(promise: Promise<Result<T, EE>>): AsyncResult<T, E | EE>;
    static wrap<T, E = Error>(promise: Promise<NonNullable<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<T>`, `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, E = Error, NullableError = Error>(callback: () => T, nullableError: NonNullable<NullableError>): Result<T, E | NullableError>;
    static wrapNullable<T, E = Error, NullError = Error, UndefinedError = Error>(callback: () => T, nullError: NonNullable<NullError>, undefinedError: NonNullable<UndefinedError>): Result<T, E | NullError | UndefinedError>;
    static wrapNullable<T, E = Error, NullableError = Error>(promise: Promise<T>, nullableError: NonNullable<NullableError>): AsyncResult<T, E | NullableError>;
    static wrapNullable<T, E = Error, NullError = Error, UndefinedError = Error>(promise: Promise<T>, nullError: NonNullable<NullError>, undefinedError: NonNullable<UndefinedError>): AsyncResult<T, E | NullError | UndefinedError>;
    /**
     * Returns a discriminated union for type-safe consumption of the result.
     * When `fallback` is provided, the error is discarded and value is returned directly.
     * When error was uncaught during transformation, it's being re-thrown here.
     *
     *   ```ts
     *
     *   // DESTRUCTURING
     *   const { val, err } = Result.ok('foo').unwrap();
     *   expect(val).toBe('foo');
     *   expect(err).toBeUndefined();
     *
     *   // FALLBACK
     *   const value = Result.err('bar').unwrap('foo');
     *   expect(val).toBe('foo');
     *
     *   ```
     */
    unwrap(): Res<T, E>;
    unwrap(fallback: NonNullable<T>): NonNullable<T>;
    /**
     * 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()`.
     *
     *   ```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, EE>(fn: (value: NonNullable<T>) => Result<U, E | EE>): Result<U, E | EE>;
    transform<U, EE>(fn: (value: NonNullable<T>) => Promise<Result<U, E | EE>>): AsyncResult<U, E | EE>;
    transform<U>(fn: (value: NonNullable<T>) => Promise<NonNullable<U>>): AsyncResult<U, E>;
    transform<U>(fn: (value: NonNullable<T>) => NonNullable<U>): Result<U, 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, E> extends Promise<Result<T, E>> {
    constructor(executor: (resolve: (value: Result<T, E> | PromiseLike<Result<T, E>>) => void, reject: (reason?: unknown) => void) => void);
    static ok<T>(val: NonNullable<T>): AsyncResult<T, never>;
    static err<E>(err: NonNullable<E>): AsyncResult<never, E>;
    static wrap<T, E = Error, EE = never>(promise: Promise<Result<T, EE>>): AsyncResult<T, E | EE>;
    static wrap<T, E = Error>(promise: Promise<NonNullable<T>>): AsyncResult<T, E>;
    static wrapNullable<T, E, NullError, UndefinedError>(promise: Promise<T>, nullError: NonNullable<NullError>, undefinedError: NonNullable<UndefinedError>): AsyncResult<T, E | NullError | UndefinedError>;
    /**
     * Returns a discriminated union for type-safe consumption of the result.
     * When `fallback` is provided, the error is discarded and value is returned directly.
     *
     *   ```ts
     *
     *   // DESTRUCTURING
     *   const { val, err } = await Result.wrap(readFile('foo.txt')).unwrap();
     *   expect(val).toBe('foo');
     *   expect(err).toBeUndefined();
     *
     *   // FALLBACK
     *   const val = await Result.wrap(readFile('foo.txt')).unwrap('bar');
     *   expect(val).toBe('bar');
     *   expect(err).toBeUndefined();
     *
     *   ```
     */
    unwrap(): Promise<Res<T, E>>;
    unwrap(fallback: NonNullable<T>): Promise<NonNullable<T>>;
    /**
     * 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()`.
     *
     *   ```ts
     *
     *   const { val, err } = await Result.wrap(
     *     http.getJson('https://api.example.com/data.json')
     *   )
     *     .transform(({ body }) => body)
     *     .unwrap();
     *
     *   ```
     */
    transform<U, EE>(fn: (value: NonNullable<T>) => Result<U, EE>): AsyncResult<U, E | EE>;
    transform<U, EE>(fn: (value: NonNullable<T>) => Promise<Result<U, EE>>): AsyncResult<U, E | EE>;
    transform<U>(fn: (value: NonNullable<T>) => Promise<NonNullable<U>>): AsyncResult<U, E>;
    transform<U>(fn: (value: NonNullable<T>) => NonNullable<U>): AsyncResult<U, E>;
}
export {};
