import { Optional } from './Optional.js';
/**
 * The `Either<R,L>` type represents 2 possible values of 2 possible types.
 *
 * A common use case it to use this to represent the outcome of a function that could
 * be an error or a value: `const result: Either<ErrorType, ValueType>`. Convention has
 * `ErrorType` as the left-value and `ValueType` as the right-value.
 *
 * The type will only ever be single-valued, but it will always be single-valued
 */
export declare class Either<L, R> {
    /**
     * Create a Left-valued `Either`
     * @param value
     */
    static left<NL, NR>(value: NL | Optional<NL>): Either<NL, NR>;
    /**
     * Create a Right-valued `Either`
     * @param value
     */
    static right<NL, NR>(value: NR | Optional<NR>): Either<NL, NR>;
    private readonly left;
    private readonly right;
    constructor(l: Optional<L>, r: Optional<R>);
    /**
     * Returns whether or not the value is left-valued
     */
    isLeft(): boolean;
    /**
     * Gets the left-value of the object.
     *
     * This will result in an error, if the object is not left-valued
     *
     * @throws {NoSuchElementException}
     */
    getLeft(): L;
    /**
     * Returns whether or not the value is right-valued
     */
    isRight(): boolean;
    /**
     * Gets the right-value of the object.
     *
     * This will result in an error, if the object is not right-valued
     *
     * @throws {NoSuchElementException}
     */
    getRight(): R;
    /**
     * Maps the `Either<L,R>` object to a simple object of type `T`.
     *
     * Each of the mapping functions must return the same type, so that this `Either` object can
     * be mapped.
     *
     * Only one of the functions will be called, so no side-effects should be relied upon.
     *
     * @param lFunc
     * @param rFunc
     */
    map<O>(lFunc: (val: L) => O | Optional<O>, rFunc: (val: R) => O | Optional<O>): O;
    map<T>(lFunc: (val: L) => T, rFunc: (val: R) => T): T;
    /**
     * Map the left-value of one type to a different value of another type.
     *
     * If this object is right-valued, then this doesn't change that, but it does
     * change the overall type of the `Either` object
     *
     * @param lFunc
     */
    mapLeft<O>(lFunc: (val: L) => Optional<O>): Either<O, R>;
    mapLeft<T>(lFunc: (val: L) => T): Either<T, R>;
    /**
     * Map the right-value of one type to a different value of another type.
     *
     * If this object is leftt-valued, then this doesn't change that, but it does
     * change the overall type of the `Either` object
     *
     * @param rFunc
     */
    mapRight<O>(rFunc: (val: R) => Optional<O>): Either<L, O>;
    mapRight<T>(rFunc: (val: R) => T): Either<L, T>;
    /**
     * Much like `{@link mapLeft}`, this converts an `Either` from one type to another.
     *
     * The difference here is that the mapping function returns an `Either` of its own, rather
     * than just a left-value. This allows you to chain a series of `Either`s together, only operating
     * if you are getting left-valued `Either`s
     *
     * @param lFunc
     */
    proceedLeft<T>(lFunc: (val: L) => Either<T, R>): Either<T, R>;
    proceedLeft<T>(lFunc: (val: L) => Promise<Either<T, R>>): Promise<Either<T, R>>;
    /**
     * Much like `{@link mapRight}`, this converts an `Either` from one type to another.
     *
     * The difference here is that the mapping function returns an `Either` of its own, rather
     * than just a right-value. This allows you to chain a series of `Either`s together, only operating
     * if you are getting right-valued `Either`s
     *
     * @param rFunc
     */
    proceedRight<T>(rFunc: (val: R) => Either<L, T>): Either<L, T>;
    proceedRight<T>(rFunc: (val: R) => Promise<Either<L, T>>): Promise<Either<L, T>>;
    /**
     * Collapses an `Either` that may contain a left-value that is an `Either`
     * @param either
     */
    static joinLeft<JL, JR>(either: Either<Either<JL, JR>, JR>): Either<JL, JR>;
    /**
     * Collapses an `Either` that may contain a right-value that is an `Either`
     * @param either
     */
    static joinRight<JL, JR>(either: Either<JL, Either<JL, JR>>): Either<JL, JR>;
    /**
     * Applies a function to the internal value. Since this returns void and takes functions that return
     * void, this relies entirely on side-effects..
     * @param lFunc
     * @param rFunc
     */
    apply(lFunc: (val: L) => void, rFunc: (val: R) => void): this;
    /**
     * Runs the provided function if the left value is populated
     */
    ifLeft(lFunc: (val: L) => void): this;
    /**
     * Runs the provided function if the right value is populated
     */
    ifRight(rFunc: (val: R) => void): this;
}
