import type { BiMapFactory } from '@rimbu/bimap/custom';
import { type BiMapCreators } from '@rimbu/bimap/custom';
import type { RMap } from '@rimbu/collection-types/map';
import type { KeyValue } from '@rimbu/collection-types/map-custom';
import type { ArrayNonEmpty, OptLazy, RelatedTo, ToJSON, TraverseState, Update } from '@rimbu/common';
import type { FastIterable, Stream, StreamSource, Streamable } from '@rimbu/stream';
/**
 * A type-invariant immutable bi-directional Map where keys and values have a one-to-one mapping.
 * See the [BiMap documentation](https://rimbu.org/docs/collections/bimap) and the [BiMap API documentation](https://rimbu.org/api/rimbu/bimap/BiMap/interface)
 * @typeparam K - the key type
 * @typeparam V - the value type
 * @example
 * ```ts
 * const b1 = BiMap.empty<number, string>()
 * const b2 = BiMap.of([1, 'a'], [2, 'b'])
 * ```
 */
export interface BiMap<K, V> extends FastIterable<readonly [K, V]> {
    /**
     * Returns the `context` associated to this collection instance.
     */
    readonly context: BiMap.Context<K, V>;
    /**
     * Returns true if the collection is empty.
     * @example
     * ```ts
     * BiMap.empty<number, number>().isEmpty   // => true
     * BiMap.of([1, 1], [2, 2]).isEmpty        // => false
     * ```
     */
    readonly isEmpty: boolean;
    /**
     * Returns the number of entries
     * @example
     * ```ts
     * BiMap.of([1, 1], [2, 2]).size       // => 2
     * ```
     */
    readonly size: number;
    /**
     * Returns true if there is at least one entry in the collection, and instructs the compiler to treat the collection
     * as a .NonEmpty type.
     * @example
     * ```ts
     * const m: BiMap<number, number> = BiMap.of([1, 1], [2, 2])
     * m.stream().first(0)     // compiler allows fallback value since the Stream may be empty
     * if (m.nonEmpty()) {
     *   m.stream().first(0)   // compiler error: fallback value not allowed since Stream is not empty
     * }
     * ```
     */
    nonEmpty(): this is BiMap.NonEmpty<K, V>;
    /**
     * Returns the collection as a .NonEmpty type
     * @throws RimbuError.EmptyCollectionAssumedNonEmptyError if the collection is empty
     * @example
     * ```ts
     * BiMap.empty<number, number>().assumeNonEmpty()   // => throws
     * const m: BiMap<number, number> = BiMap.of([1, 1], [2, 2])
     * const m2: BiMap.NonEmpty<number, number> = m     // => compiler error
     * const m3: BiMap.NonEmpty<number, number> = m.assumeNonEmpty()
     * ```
     * @note returns reference to this collection
     */
    assumeNonEmpty(): BiMap.NonEmpty<K, V>;
    /**
     * Returns the Map representation of the key to value mapping.
     * @example
     * ```ts
     * BiMap.of([1, 10], [2, 20]).keyValueMap.toArray()
     * // => [[1, 10], [2, 20]]
     * ```
     */
    readonly keyValueMap: RMap<K, V>;
    /**
     * Returns the Map representation of the key to value mapping.
     * @example
     * ```ts
     * BiMap.of([1, 10], [2, 20]).valueKeyMap.toArray()
     * // => [[10, 1], [20, 2]]
     * ```
     */
    readonly valueKeyMap: RMap<V, K>;
    /**
     * Returns true if the given `key` is present in the collection.
     * @param key - the key to look for
     * @example
     * ```ts
     * const m = BiMap.of([1, 'a'], [2, 'b'])
     * m.hasKey(2)    // => true
     * m.hasKey(3)    // => false
     * ```
     */
    hasKey<UK = K>(key: RelatedTo<K, UK>): boolean;
    /**
     * Returns true if the given `value` is present in the collection.
     * @param value - the value to look for
     * @example
     * ```ts
     * const m = BiMap.of([1, 'a'], [2, 'b'])
     * m.hasKey('a')    // => true
     * m.hasKey('z')    // => false
     * ```
     */
    hasValue<UV = V>(key: RelatedTo<V, UV>): boolean;
    /**
     * Returns the value associated with the given `key`, or given `otherwise` value if the key is not in the collection.
     * @param key - the key to look for
     * @param otherwise - (default: undefined) an `OptLazy` fallback value if the key is not in the collection
     * @example
     * ```ts
     * const m = BiMap.of([1, 'a'], [2, 'b'])
     * m.getValue(2)          // => 'b'
     * m.getValue(3)          // => undefined
     * m.getValue(2, 'none')  // => 'b'
     * m.getValue(3, 'none')  // => 'none'
     * ```
     */
    getValue<UK = K>(key: RelatedTo<K, UK>): V | undefined;
    getValue<UK, O>(key: RelatedTo<K, UK>, otherwise: OptLazy<O>): V | O;
    /**
     * Returns the key associated with the given `value`, or given `otherwise` value if the key is not in the collection.
     * @param value - thevalue to look for
     * @param otherwise - (default: undefined) an `OptLazy` fallback value if the value is not in the collection
     * @example
     * ```ts
     * const m = BiMap.of([1, 'a'], [2, 'b'])
     * m.getKey('b')          // => 2
     * m.getKey('z')          // => undefined
     * m.getKey('b', 'none')  // => 2
     * m.getKey('z', 'none')  // => 'none'
     * ```
     */
    getKey<UV = V>(value: RelatedTo<V, UV>): K | undefined;
    getKey<UV, O>(value: RelatedTo<V, UV>, otherwise: OptLazy<O>): K | O;
    /**
     * Returns the collection with the given `key` associated to the given `value`.
     * @param key - the entry key to add
     * @param value - the entry value to add
     * @example
     * ```ts
     * BiMap.of([1, 1], [2, 2]).set(1, 2).toArray()
     * // => [[1, 2]]
     * ```
     * @note if the key and/or value are already associated, the previous value will be 'replaced'
     */
    set(key: K, value: V): BiMap.NonEmpty<K, V>;
    /**
     * Returns the collection with given `entry` added.
     * @param entry - a tuple containing a key and value
     * @example
     * ```ts
     * BiMap.of([1, 1], [2, 2]).addEntry([1, 2]).toArray()
     * // => [[1, 2]]
     * ```
     */
    addEntry(entry: readonly [K, V]): BiMap.NonEmpty<K, V>;
    /**
     * Returns the collection with the entries from the given `StreamSource` `entries` added.
     * @param entries - a `StreamSource` containing tuples with a key and value
     * @example
     * ```ts
     * BiMap.of([1, 1]).addEntries([[2, 2], [1, 3]]).toArray()
     * // => [[1, 3], [2, 2]]
     * ```
     */
    addEntries(entries: StreamSource.NonEmpty<readonly [K, V]>): BiMap.NonEmpty<K, V>;
    addEntries(entries: StreamSource<readonly [K, V]>): BiMap<K, V>;
    /**
     * Returns the collection where the entry associated with given `key` is removed if it was part of the collection.
     * @param key - the key of the entry to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.removeKey(2).toArray()   // => [[1, 1]]
     * m.removeKey(3) === m       // true
     * ```
     * @note guarantees same object reference if the key is not present
     */
    removeKey<UK = K>(key: RelatedTo<K, UK>): BiMap<K, V>;
    /**
     * Returns a tuple containing the collection of which the entry associated with given `key` is removed, and the value that
     * is associated with that key. If the key is not present, it will return undefined instead.
     * @param key - the key of the entry to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * const result = m.removeKeyAndGet(2)
     * if (result !== undefined) console.log([result[0].toString(), result[1]])    // => logs [BiMap(1 <=> 1), 2]
     * console.log(m.removeKeyAndGet(3))                                           // => logs undefined
     * ```
     */
    removeKeyAndGet<UK = K>(key: RelatedTo<K, UK>): [BiMap<K, V>, V] | undefined;
    /**
     * Returns the collection where the entries associated with each key in given `keys` are removed if they were present.
     * @param keys - a `StreamSource` of keys to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.removeKeys([1, 3]).toArray()     // => [[2, 2]]
     * m.removeKeys([1, 3, 2]).toArray()  // => []
     * m.removeKeys([3, 4, 5]) === m      // => true
     * ```
     * @note guarantees same object reference if none of the keys are present
     */
    removeKeys<UK = K>(keys: StreamSource<RelatedTo<K, UK>>): BiMap<K, V>;
    /**
     * Returns the collection where the entry associated with given `value` is removed if it was part of the collection.
     * @param value - the value of the entry to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.removeValue(2).toArray()   // => [[1, 1]]
     * m.removeValue(3) === m       // true
     * ```
     * @note guarantees same object reference if the key is not present
     */
    removeValue<UV = V>(value: RelatedTo<V, UV>): BiMap<K, V>;
    /**
     * Returns a tuple containing the collection of which the entry associated with given `value` is removed, and the key that
     * is associated with that value. If the value is not present, it will return undefined instead.
     * @param value - the value of the entry to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * const result = m.removeValueAndGet(2)
     * if (result !== undefined) console.log([result[0].toString(), result[1]])    // => logs [BiMap(1 <=> 1), 2]
     * console.log(m.removeValueAndGet(3))                                           // => logs undefined
     * ```
     */
    removeValueAndGet<UV = V>(value: RelatedTo<V, UV>): [BiMap<K, V>, K] | undefined;
    /**
     * Returns the collection where the entries associated with each value in given `values` are removed if they were present.
     * @param values - a `StreamSource` of values to remove
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.removeValues([1, 3]).toArray()     // => [[2, 2]]
     * m.removeValues([1, 3, 2]).toArray()  // => []
     * m.removeValues([3, 4, 5]) === m      // => true
     * ```
     * @note guarantees same object reference if none of the keys are present
     */
    removeValues<UV = V>(value: StreamSource<RelatedTo<V, UV>>): BiMap<K, V>;
    /**
     * Returns the collection where the value associated with given `key` is updated with the given `valueUpdate` value or update function.
     * @param key - the key of the entry to update
     * @param valueUpdate - a new value or function taking the current value and returning a new value
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.updateValueAtKey(3, 3).toArray()
     * // => [[1, 1], [2, 2]]
     * m.updateValueAtKey(2, 10).toArray()
     * // => [[1, 1], [2, 10]]
     * m.updateValueAtKey(1, v => v + 1)
     * // => [[1, 2]]
     * ```
     */
    updateValueAtKey<UK = K>(key: RelatedTo<K, UK>, valueUpdate: Update<V>): BiMap<K, V>;
    /**
     * Returns the collection where the key associated with given `value` is updated with the given `keyUpdate` value or update function.
     * @param keyUpdate - a new value or function taking the current key and returning a new key
     * @param value - the value of the entry to update
     * @example
     * ```ts
     * const m = BiMap.of([1, 1], [2, 2])
     * m.updateKeyAtValue(3, 3).toArray()
     * // => [[1, 1], [2, 2]]
     * m.updateKeyAtValue(10, 2).toArray()
     * // => [[1, 1], [10, 2]]
     * m.updateKeyAtValue((v) => v + 1, 1)
     * // => [[2, 1]]
     * ```
     */
    updateKeyAtValue<UV = V>(keyUpdate: Update<K>, value: RelatedTo<V, UV>): BiMap<K, V>;
    /**
     * Returns a `Stream` containing all entries of this collection as tuples of key and value.
     * @example
     * ```ts
     * BiMap.of([1, 1], [2, 2]).stream().toArray()  // => [[1, 1], [2, 2]]
     * ```
     */
    stream(): Stream<readonly [K, V]>;
    /**
     * Returns a `Stream` containing all keys of this collection.
     * @example
     * ```ts
     * BiMap.of([[1, 'a'], [2, 'b']]).streamKeys().toArray()   // => [1, 2]
     * ```
     */
    streamKeys(): Stream<K>;
    /**
     * Returns a `Stream` containing all values of this collection.
     * @example
     * ```ts
     * BiMap.of([[1, 'a'], [2, 'b']]).streamValues().toArray()   // => ['a', 'b']
     * ```
     */
    streamValues(): Stream<V>;
    /**
     * Performs given function `f` for each entry of the collection, using given `state` as initial traversal state.
     * @param f - the function to perform for each entry, receiving:<br/>
     * - `entry`: the next tuple of a key and value<br/>
     * - `index`: the index of the element<br/>
     * - `halt`: a function that, if called, ensures that no new elements are passed
     * @param options - (optional) an object containing the following properties:<br/>
     * - state: (optional) the traverse state
     * @example
     * ```ts
     * BiMap.of([1, 'a'], [2, 'b'], [3, 'c']).forEach((entry, i, halt) => {
     *  console.log([entry[1], entry[0]]);
     *  if (i >= 1) halt();
     * })
     * // => logs ['a', 1]  ['b', 2]
     * ```
     * @note O(N)
     */
    forEach(f: (entry: readonly [K, V], index: number, halt: () => void) => void, options?: {
        state?: TraverseState;
    }): void;
    /**
     * Returns a collection containing only those entries that satisfy given `pred` predicate.
     * @param pred - a predicate function receiving:<br/>
     * - `entry`: the next entry<br/>
     * - `index`: the entry index<br/>
     * - `halt`: a function that, when called, ensures no next elements are passed
     * @param options - (optional) an object containing the following properties:<br/>
     * - negate: (default: false) when true will negate the given predicate
     * @example
     * ```ts
     * BiMap.of([1, 'a'], [2, 'b'], [3, 'c']).filter(entry => entry[0] === 2 || entry[1] === 'c').toArray()
     * // => [[2, 'b'], [3, 'c']]
     * ```
     */
    filter(pred: (entry: readonly [K, V], index: number, halt: () => void) => boolean, options?: {
        negate?: boolean;
    }): BiMap<K, V>;
    /**
     * Returns a builder object containing the entries of this collection.
     * @example
     * ```ts
     * const builder: BiMap.Builder<number, string> = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
     * ```
     */
    toBuilder(): BiMap.Builder<K, V>;
    /**
     * Returns an array containing all entries in this collection.
     * @example
     * ```ts
     * BiMap.of([1, 'a'], [2, 'b']).toArray()   // => [[1, 'a'], [2, 'b']]
     * ```
     * @note O(log(N))
     * @note it is safe to mutate the returned array, however, the array elements are not copied, thus should be treated as read-only
     */
    toArray(): (readonly [K, V])[];
    /**
     * Returns a string representation of this collection.
     * @example
     * ```ts
     * BiMap.of([1, 'a'], [2, 'b']).toString()   // => BiMap(1 <=> 'a', 2 <=> 'b')
     * ```
     */
    toString(): string;
    /**
     * Returns a JSON representation of this collection.
     * @example
     * ```ts
     * BiMap.of([1, 'a'], [2, 'b']).toJSON()   // => { dataType: 'BiMap', value: [[1, 'a'], [2, 'b']] }
     * ```
     */
    toJSON(): ToJSON<(readonly [K, V])[], this['context']['typeTag']>;
}
export declare namespace BiMap {
    /**
     * A non-empty type-invariant immutable bi-directional Map where keys and values have a one-to-one mapping.
     * See the [BiMap documentation](https://rimbu.org/docs/collections/bimap) and the [BiMap API documentation](https://rimbu.org/api/rimbu/bimap/BiMap/interface)   * @typeparam K - the key type
     * @typeparam V - the value type
     */
    interface NonEmpty<K, V> extends BiMap<K, V>, Streamable.NonEmpty<readonly [K, V]> {
        /**
         * Returns false since this collection is known to be non-empty.
         * @example
         * ```ts
         * BiMap.of([1, 1], [2, 2]).isEmpty   // => false
         * ```
         */
        readonly isEmpty: false;
        /**
         * Returns true since this collection is known to be non-empty
         * @example
         * ```ts
         * BiMap.of([1, 1], [2, 2]).nonEmpty()   // => true
         * ```
         */
        nonEmpty(): this is BiMap.NonEmpty<K, V>;
        /**
         * Returns a self reference since this collection is known to be non-empty.
         * @example
         * ```ts
         * const m = BiMap.of([1, 1], [2, 2]);
         * m === m.assumeNonEmpty()  // => true
         * ```
         */
        assumeNonEmpty(): this;
        /**
         * Returns this collection typed as a 'possibly empty' collection.
         * @example
         * ```ts
         * BiMap.of([1, 1], [2, 2]).asNormal();  // type: BiMap<number, number>
         * ```
         */
        asNormal(): BiMap<K, V>;
        /**
         * Returns the non-empty Map representation of the key to value mapping.
         * @example
         * ```ts
         * BiMap.of([1, 10], [2, 20]).keyValueMap.toArray()
         * // => [[1, 10], [2, 20]]
         * ```
         */
        readonly keyValueMap: RMap.NonEmpty<K, V>;
        /**
         * Returns the non-empty Map representation of the key to value mapping.
         * @example
         * ```ts
         * BiMap.of([1, 10], [2, 20]).valueKeyMap.toArray()
         * // => [[10, 1], [20, 2]]
         * ```
         */
        readonly valueKeyMap: RMap.NonEmpty<V, K>;
        /**
         * Returns the collection with the entries from the given `StreamSource` `entries` added.
         * @param entries - a `StreamSource` containing tuples with a key and value
         * @example
         * ```ts
         * BiMap.of([1, 1]).addEntries([[2, 2], [1, 3]]).toArray()
         * // => [[1, 2]]
         * ```
         */
        addEntries(entries: StreamSource<readonly [K, V]>): BiMap.NonEmpty<K, V>;
        /**
         * Returns the collection where the value associated with given `key` is updated with the given `update` value or update function.
         * @param key - the key of the entry to update
         * @param valueUpdate - a new value or function taking the current value and returning a new value
         * @example
         * ```ts
         * const m = BiMap.of([1, 1], [2, 2])
         * m.updateValueAt(3, 3).toArray()
         * // => [[1, 1], [2, 2]]
         * m.updateValueAt(2, 10).toArray()
         * // => [[1, 1], [2, 10]]
         * m.updateValueAt(1, v => v + 1)
         * // => [[1, 2]]
         * ```
         */
        updateValueAtKey<UK = K>(key: RelatedTo<K, UK>, valueUpdate: Update<V>): BiMap.NonEmpty<K, V>;
        /**
         * Returns the collection where the key associated with given `value` is updated with the given `update` value or update function.
         * @param keyUpdate - a new value or function taking the current key and returning a new key
         * @param value - the value of the entry to update
         * @example
         * ```ts
         * const m = BiMap.of([1, 1], [2, 2])
         * m.updateKeyAtValue(3, 3).toArray()
         * // => [[1, 1], [2, 2]]
         * m.updateKeyAtValue(10, 2).toArray()
         * // => [[1, 1], [10, 2]]
         * m.updateKeyAtValue((v) => v + 1, 1)
         * // => [[2, 1]]
         * ```
         */
        updateKeyAtValue<UV = V>(keyUpdate: Update<K>, value: RelatedTo<V, UV>): BiMap.NonEmpty<K, V>;
        /**
         * Returns a non-empty `Stream` containing all entries of this collection as tuples of key and value.
         * @example
         * ```ts
         * BiMap.of([1, 1], [2, 2]).stream().toArray()  // => [[1, 1], [2, 2]]
         * ```
         */
        stream(): Stream.NonEmpty<readonly [K, V]>;
        /**
         * Returns a non-empty `Stream` containing all keys of this collection.
         * @example
         * ```ts
         * BiMap.of([[1, 'a'], [2, 'b']]).streamKeys().toArray()   // => [1, 2]
         * ```
         */
        streamKeys(): Stream.NonEmpty<K>;
        /**
         * Returns a non-empty `Stream` containing all values of this collection.
         * @example
         * ```ts
         * BiMap.of([[1, 'a'], [2, 'b']]).streamValues().toArray()   // => ['a', 'b']
         * ```
         */
        streamValues(): Stream.NonEmpty<V>;
        /**
         * Returns a non-empty array containing all entries in this collection.
         * @example
         * ```ts
         * BiMap.of([1, 'a'], [2, 'b']).toArray()   // => [[1, 'a'], [2, 'b']]
         * ```
         * @note O(log(N))
         * @note it is safe to mutate the returned array, however, the array elements are not copied, thus should be treated as read-only
         */
        toArray(): ArrayNonEmpty<readonly [K, V]>;
    }
    /**
     * The BiMap's Context instance that serves as a factory for all related immutable instances and builders.
     * @typeparam UK - the upper type limit for key types for which this context can create instances
     * @typeparam UV - the upper type limit for value types for which this context can create instances
     */
    interface Context<UK, UV, Tp extends BiMap.Types = BiMap.Types> extends BiMapFactory<UK, UV> {
        /**
         * A string tag defining the specific collection type
         * @example
         * ```ts
         * BiMap.defaultContext().typeTag   // => 'BiMap'
         * ```
         */
        readonly typeTag: 'BiMap';
        readonly _types: Tp;
        readonly keyValueContext: RMap.Context<UK>;
        readonly valueKeyContext: RMap.Context<UV>;
    }
    /**
     * A mutable `BiMap` builder used to efficiently create new immutable instances.
     * See the [BiMap documentation](https://rimbu.org/docs/collections/bimap) and the [BiMap.Builder API documentation](https://rimbu.org/api/rimbu/bimap/BiMap/Builder/interface)
     * @typeparam K - the key type
     * @typeparam V - the value type
     */
    interface Builder<K, V> {
        /**
         * Returns the amount of entries in the builder.
         * @example
         * ```ts
         * BiMap.of([[1, 'a'], [2, 'b']]).toBuilder().size
         * // => 2
         * ```
         */
        readonly size: number;
        /**
         * Returns true if there are no entries in the builder.
         * @example
         * ```ts
         * BiMap.of([[1, 'a'], [2, 'b']]).toBuilder().isEmpty
         * // => false
         * ```
         */
        readonly isEmpty: boolean;
        /**
         * Returns the value associated with the given `key`, or given `otherwise` value if the key is not in the collection.
         * @param key - the key to look for
         * @param otherwise - (default: undefined) an `OptLazy` fallback value if the key is not in the collection
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.getValue(2)          // => 'b'
         * m.getValue(3)          // => undefined
         * m.getValue(2, 'none')  // => 'b'
         * m.getValue(3, 'none')  // => 'none'
         * ```
         */
        getValue<UK = K>(key: RelatedTo<K, UK>): V | undefined;
        getValue<UK, O>(key: RelatedTo<K, UK>, otherwise: OptLazy<O>): V | O;
        /**
         * Returns the key associated with the given `value`, or given `otherwise` value if the value is not in the collection.
         * @param value - the value to look for
         * @param otherwise - (default: undefined) an `OptLazy` fallback value if the value is not in the collection
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.getKey('b')          // => 2
         * m.getKey('z')          // => undefined
         * m.getKey('b', 'none')  // => 2
         * m.getKey('z', 'none')  // => 'none'
         * ```
         */
        getKey<UV = V>(value: RelatedTo<V, UV>): K | undefined;
        getKey<UV, O>(value: RelatedTo<V, UV>, otherwise: OptLazy<O>): K | O;
        /**
         * Returns true if the given `key` is present in the builder.
         * @param key - the key to look for
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.hasKey(2)    // => true
         * m.hasKey(3)    // => false
         * ```
         */
        hasKey<UK = K>(key: RelatedTo<K, UK>): boolean;
        /**
         * Returns true if the given `value` is present in the builder.
         * @param value - the value to look for
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.hasValue('a')    // => true
         * m.hasValue('z')    // => false
         * ```
         */
        hasValue<UV = V>(value: RelatedTo<V, UV>): boolean;
        /**
         * Associates given `key` with given `value` in the builder.
         * @param key - the entry key
         * @param value - the entry value
         * @returns true if the data in the builder has changed
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.set(1, 'a')   // => false
         * m.set(1, 'b')   // => true
         * ```
         */
        set(key: K, value: V): boolean;
        /**
         * Adds the given `entry` to the builder, where the entry key is associated with the entry value.
         * @param entry - the entry to add
         * @returns true if the data in the builder has changed
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.addEntry([1, 'a'])   // => false
         * m.addEntry([1, 'b'])   // => true
         * ```
         */
        addEntry(entry: readonly [K, V]): boolean;
        /**
         * Adds given `entries` to the builder.
         * @param entries - a `StreamSource` containing the entries to add
         * @returns true if the data in the builder has changed
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.addEntries([1, 'a'], [3, 'c']])   // => true
         * m.addEntries([])                    // => false
         * ```
         */
        addEntries(entries: StreamSource<readonly [K, V]>): boolean;
        /**
         * Removes the entries related to given `key` from the builder.
         * @param key - the key to remove
         * @param otherwise - (default: undefined) the value to return if the key is not in the builder
         * @returns the value previously associated with given `key`, or the fallback value otherwise
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.removeKey(2)        // => 'b'
         * m.removeKey(3)        // => undefined
         * m.removeKey(3, 'c')   // => 'c'
         * ```
         */
        removeKey<UK = K>(key: RelatedTo<K, UK>): V | undefined;
        removeKey<UK, O>(key: RelatedTo<K, UK>, otherwise: OptLazy<O>): V | O;
        /**
         * Removes the entries related to the given `keys` `StreamSource` from the builder.
         * @param keys - the `StreamSource` containing the keys to remove.
         * @returns true if the data in the builder has changed
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.removeKeys([3, 4, 5])  // => false
         * m.removeKeys([1, 10])    // => true
         * ```
         */
        removeKeys<UK = K>(keys: StreamSource<RelatedTo<K, UK>>): boolean;
        /**
         * Removes the entries related to given `value` from the builder.
         * @param value - the value to remove
         * @param otherwise - (default: undefined) the key to return if the value is not in the builder
         * @returns the key previously associated with given `value`, or the fallback value otherwise
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.removeValue('b')        // => 2
         * m.removeValue('c')        // => undefined
         * m.removeValue('c', 0)     // => 0
         * ```
         */
        removeValue<UV = V>(value: RelatedTo<V, UV>): K | undefined;
        removeValue<UV, O>(value: RelatedTo<V, UV>, otherwise: OptLazy<O>): K | O;
        /**
         * Removes the entries related to the given `values` `StreamSource` from the builder.
         * @param values - the `StreamSource` containing the values to remove.
         * @returns true if the data in the builder has changed
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * m.removeValues(['c', 'd', 'e'])  // => false
         * m.removeValues(['a', 'e'])       // => true
         * ```
         */
        removeValues<UV = V>(values: StreamSource<RelatedTo<V, UV>>): boolean;
        /**
         * Performs given function `f` for each entry of the builder.
         * @param f - the function to perform for each element, receiving:<br/>
         * - `entry`: the next key-value entry<br/>
         * - `index`: the index of the element<br/>
         * - `halt`: a function that, if called, ensures that no new elements are passed
         * @param options - (optional) an object containing the following properties:<br/>
         * - state: (optional) the traverse state
         * @throws RibuError.ModifiedBuilderWhileLoopingOverItError if the builder is modified while
         * looping over it
         * @example
         * ```ts
         * BiMap.of([1, 'a'], [2, 'b'], [3, 'c']).toBuilder().forEach((entry, i, halt) => {
         *  console.log([entry[1], entry[0]]);
         *  if (i >= 1) halt();
         * })
         * // => logs ['a', 1]  ['b', 2]
         * ```
         * @note O(N)
         */
        forEach(f: (entry: readonly [K, V], index: number, halt: () => void) => void, options?: {
            state?: TraverseState;
        }): void;
        /**
         * Returns an immutable collection instance containing the entries in this builder.
         * @example
         * ```ts
         * const m = BiMap.of([1, 'a'], [2, 'b']).toBuilder()
         * const m2: BiMap<number, string> = m.build()
         * ```
         */
        build(): BiMap<K, V>;
    }
    /**
     * Utility interface that provides higher-kinded types for this collection.
     */
    interface Types extends KeyValue {
        /**
         * The 'normal' collection type (higher-kinded type).
         */
        readonly normal: BiMap<this['_K'], this['_V']>;
        /**
         * The 'non-empty' collection type (higher-kinded type).
         */
        readonly nonEmpty: BiMap.NonEmpty<this['_K'], this['_V']>;
    }
}
export declare const BiMap: BiMapCreators;
