import { Option } from './option.js';
import { AsyncResult } from './asyncresult.js';
interface BaseResult<T, E> extends Iterable<T> {
    /** `true` when the result is Ok */
    isOk(): this is OkImpl<T>;
    /** `true` when the result is Err */
    isErr(): this is ErrImpl<E>;
    /**
     * Returns the contained `Ok` value, if exists.  Throws an error if not.
     *
     * The thrown error's
     * [`cause'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)
     * is set to value contained in `Err`.
     *
     * If you know you're dealing with `Ok` and the compiler knows it too (because you tested
     * `isOk()` or `isErr()`) you should use `value` instead. While `Ok`'s `expect()` and `value` will
     * both return the same value using `value` is preferable because it makes it clear that
     * there won't be an exception thrown on access.
     *
     * @param msg the message to throw if no Ok value.
     */
    expect(msg: string): T;
    /**
     * Returns the contained `Err` value, if exists.  Throws an error if not.
     * @param msg the message to throw if no Err value.
     */
    expectErr(msg: string): E;
    /**
     * Returns the contained `Ok` value.
     * Because this function may throw, its use is generally discouraged.
     * Instead, prefer to handle the `Err` case explicitly.
     *
     * If you know you're dealing with `Ok` and the compiler knows it too (because you tested
     * `isOk()` or `isErr()`) you should use `value` instead. While `Ok`'s `unwrap()` and `value` will
     * both return the same value using `value` is preferable because it makes it clear that
     * there won't be an exception thrown on access.
     *
     * Throws if the value is an `Err`, with a message provided by the `Err`'s value and
     * [`cause'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)
     * set to the value.
     */
    unwrap(): T;
    /**
     * Returns the contained `Err` value.
     * Because this function may throw, its use is generally discouraged.
     * Instead, prefer to handle the `Ok` case explicitly and access the `error` property
     * directly.
     *
     * Throws if the value is an `Ok`, with a message provided by the `Ok`'s value and
     * [`cause'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause)
     * set to the value.
     */
    unwrapErr(): E;
    /**
     * Returns the contained `Ok` value or a provided default.
     *
     *  @see unwrapOr
     *  @deprecated in favor of unwrapOr
     */
    else<T2>(val: T2): T | T2;
    /**
     * Returns the contained `Ok` value or a provided default.
     *
     *  (This is the `unwrap_or` in rust)
     */
    unwrapOr<T2>(val: T2): T | T2;
    /**
     * Returns the contained `Ok` value or computes a value with a provided function.
     *
     * The function is called at most one time, only if needed.
     *
     * @example
     * ```
     * Ok('OK').unwrapOrElse(
     *     (error) => { console.log(`Called, got ${error}`); return 'UGH'; }
     * ) // => 'OK', nothing printed
     *
     * Err('A03B').unwrapOrElse((error) => `UGH, got ${error}`) // => 'UGH, got A03B'
     * ```
     */
    unwrapOrElse<T2>(f: (error: E) => T2): T | T2;
    /**
     * Calls `mapper` if the result is `Ok`, otherwise returns the `Err` value of self.
     * This function can be used for control flow based on `Result` values.
     */
    andThen<T2>(mapper: (val: T) => Ok<T2>): Result<T2, E>;
    andThen<E2>(mapper: (val: T) => Err<E2>): Result<T, E | E2>;
    andThen<T2, E2>(mapper: (val: T) => Result<T2, E2>): Result<T2, E | E2>;
    andThen<T2, E2>(mapper: (val: T) => Result<T2, E2>): Result<T2, E | E2>;
    /**
     * Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a contained `Ok` value,
     * leaving an `Err` value untouched.
     *
     * This function can be used to compose the results of two functions.
     */
    map<U>(mapper: (val: T) => U): Result<U, E>;
    /**
     * Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a contained `Err` value,
     * leaving an `Ok` value untouched.
     *
     * This function can be used to pass through a successful result while handling an error.
     */
    mapErr<F>(mapper: (val: E) => F): Result<T, F>;
    /**
     * Maps a `Result<T, E>` to `Result<U, E>` by either converting `T` to `U` using `mapper`
     * (in case of `Ok`) or using the `default_` value (in case of `Err`).
     *
     * If `default` is a result of a function call consider using `mapOrElse` instead, it will
     * only evaluate the function when needed.
     */
    mapOr<U>(default_: U, mapper: (val: T) => U): U;
    /**
     * Maps a `Result<T, E>` to `Result<U, E>` by either converting `T` to `U` using `mapper`
     * (in case of `Ok`) or producing a default value using the `default` function (in case of
     * `Err`).
     */
    mapOrElse<U>(default_: (error: E) => U, mapper: (val: T) => U): U;
    /**
     * Returns `Ok()` if we have a value, otherwise returns `other`.
     *
     * `other` is evaluated eagerly. If `other` is a result of a function
     * call try `orElse()` instead – it evaluates the parameter lazily.
     *
     * @example
     *
     * Ok(1).or(Ok(2)) // => Ok(1)
     * Err('error here').or(Ok(2)) // => Ok(2)
     */
    or<E2>(other: Result<T, E2>): Result<T, E2>;
    /**
     * Returns `Ok()` if we have a value, otherwise returns the result
     * of calling `other()`.
     *
     * `other()` is called *only* when needed and is passed the error value in a parameter.
     *
     * @example
     *
     * Ok(1).orElse(() => Ok(2)) // => Ok(1)
     * Err('error').orElse(() => Ok(2)) // => Ok(2)
     */
    orElse<E2>(other: (error: E) => Result<T, E2>): Result<T, E2>;
    /**
     *  Converts from `Result<T, E>` to `Option<T>`, discarding the error if any
     *
     *  Similar to rust's `ok` method
     */
    toOption(): Option<T>;
    /**
     * Creates an `AsyncResult` based on this `Result`.
     *
     * Useful when you need to compose results with asynchronous code.
     */
    toAsyncResult(): AsyncResult<T, E>;
}
/**
 * Contains the error value
 */
export declare class ErrImpl<E> implements BaseResult<never, E> {
    /** An empty Err */
    static readonly EMPTY: ErrImpl<void>;
    isOk(): this is OkImpl<never>;
    isErr(): this is ErrImpl<E>;
    readonly error: E;
    private readonly _stack;
    [Symbol.iterator](): Iterator<never, never, any>;
    constructor(val: E);
    /**
     * @deprecated in favor of unwrapOr
     * @see unwrapOr
     */
    else<T2>(val: T2): T2;
    unwrapOr<T2>(val: T2): T2;
    unwrapOrElse<T2>(f: (error: E) => T2): T2;
    expect(msg: string): never;
    expectErr(_msg: string): E;
    unwrap(): never;
    unwrapErr(): E;
    map(_mapper: unknown): Err<E>;
    andThen(op: unknown): Err<E>;
    mapErr<E2>(mapper: (err: E) => E2): Err<E2>;
    mapOr<U>(default_: U, _mapper: unknown): U;
    mapOrElse<U>(default_: (error: E) => U, _mapper: unknown): U;
    or<T>(other: Ok<T>): Result<T, never>;
    or<R extends Result<any, any>>(other: R): R;
    orElse<T>(other: (error: E) => Ok<T>): Result<T, never>;
    orElse<R extends Result<any, any>>(other: (error: E) => R): R;
    toOption(): Option<never>;
    toString(): string;
    get stack(): string | undefined;
    toAsyncResult(): AsyncResult<never, E>;
}
export declare const Err: typeof ErrImpl & (<E>(err: E) => Err<E>);
export type Err<E> = ErrImpl<E>;
/**
 * Contains the success value
 */
export declare class OkImpl<T> implements BaseResult<T, never> {
    static readonly EMPTY: OkImpl<void>;
    isOk(): this is OkImpl<T>;
    isErr(): this is ErrImpl<never>;
    readonly value: T;
    [Symbol.iterator](): Iterator<T>;
    constructor(val: T);
    /**
     * @see unwrapOr
     * @deprecated in favor of unwrapOr
     */
    else(_val: unknown): T;
    unwrapOr(_val: unknown): T;
    unwrapOrElse(_f: unknown): T;
    expect(_msg: string): T;
    expectErr(msg: string): never;
    unwrap(): T;
    unwrapErr(): never;
    map<T2>(mapper: (val: T) => T2): Ok<T2>;
    andThen<T2>(mapper: (val: T) => Ok<T2>): Ok<T2>;
    andThen<E2>(mapper: (val: T) => Err<E2>): Result<T, E2>;
    andThen<T2, E2>(mapper: (val: T) => Result<T2, E2>): Result<T2, E2>;
    mapErr(_mapper: unknown): Ok<T>;
    mapOr<U>(_default_: U, mapper: (val: T) => U): U;
    mapOrElse<U>(_default_: (_error: never) => U, mapper: (val: T) => U): U;
    or(_other: Result<T, any>): Ok<T>;
    orElse(_other: (error: never) => Result<T, any>): Ok<T>;
    toOption(): Option<T>;
    /**
     * Returns the contained `Ok` value, but never throws.
     * Unlike `unwrap()`, this method doesn't throw and is only callable on an Ok<T>
     *
     * Therefore, it can be used instead of `unwrap()` as a maintainability safeguard
     * that will fail to compile if the error type of the Result is later changed to an error that can actually occur.
     *
     * (this is the `into_ok()` in rust)
     */
    safeUnwrap(): T;
    toString(): string;
    toAsyncResult(): AsyncResult<T, never>;
}
export declare const Ok: typeof OkImpl & (<T>(val: T) => Ok<T>);
export type Ok<T> = OkImpl<T>;
export type Result<T, E> = Ok<T> | Err<E>;
export type ResultOkType<T extends Result<any, any>> = T extends Ok<infer U> ? U : never;
export type ResultErrType<T> = T extends Err<infer U> ? U : never;
export type ResultOkTypes<T extends Result<any, any>[]> = {
    [key in keyof T]: T[key] extends Result<infer U, any> ? ResultOkType<T[key]> : never;
};
export type ResultErrTypes<T extends Result<any, any>[]> = {
    [key in keyof T]: T[key] extends Result<infer U, any> ? ResultErrType<T[key]> : never;
};
export declare namespace Result {
    /**
     * Parse a set of `Result`s, returning an array of all `Ok` values.
     * Short circuits with the first `Err` found, if any
     */
    function all<const T extends Result<any, any>[]>(results: T): Result<ResultOkTypes<T>, ResultErrTypes<T>[number]>;
    /**
     * Parse a set of `Result`s, short-circuits when an input value is `Ok`.
     * If no `Ok` is found, returns an `Err` containing the collected error values
     */
    function any<const T extends Result<any, any>[]>(results: T): Result<ResultOkTypes<T>[number], ResultErrTypes<T>>;
    /**
     * Wrap an operation that may throw an Error (`try-catch` style) into checked exception style
     * @param op The operation function
     */
    function wrap<T, E = unknown>(op: () => T): Result<T, E>;
    /**
     * Wrap an async operation that may throw an Error (`try-catch` style) into checked exception style
     * @param op The operation function
     */
    function wrapAsync<T, E = unknown>(op: () => Promise<T>): Promise<Result<T, E>>;
    /**
     * Partitions a set of results, separating the `Ok` and `Err` values.
     */
    function partition<T extends Result<any, any>[]>(results: T): [ResultOkTypes<T>, ResultErrTypes<T>];
    function isResult<T = any, E = any>(val: unknown): val is Result<T, E>;
}
export {};
//# sourceMappingURL=result.d.ts.map