import type { Update } from '@rimbu/common';
/**
 * A readonly array of fixed length and types.
 */
export type Tuple<T extends Tuple.Source> = Readonly<T>;
export declare namespace Tuple {
    /**
     * A non-empty readonly array that can serve as a source for a Tuple.
     */
    type NonEmptySource = readonly [unknown, ...unknown[]];
    /**
     * A readonly array that can serve as a source for a Tuple.
     */
    type Source = readonly unknown[];
    /**
     * Determines whether the given type `T` is a tuple type.
     * @typeparam T - the input type
     */
    type IsTuple<T> = T extends {
        length: infer L;
    } ? 0 extends L ? false : true : false;
    /**
     * Returns the indices/keys that are in a tuple.
     * @typeparam T - the input tuple type
     */
    type KeysOf<T> = {
        [K in keyof T]: K;
    }[keyof T & number];
    /**
     * Convenience method to type Tuple types
     * @param values - the values of the tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * // type of t => Tuple<[number, string, boolean]>
     * ```
     */
    function of<T extends Tuple.NonEmptySource>(...values: T): Tuple<T>;
    /**
     * Returns the item at the given `index` in the given `tuple`.
     * @param tuple - the tuple to get the item from
     * @param index - the index in of the tuple element
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.getIndex(t, 1))
     * // => 'a'
     * ```
     */
    function getIndex<T extends Tuple.Source, K extends keyof T = keyof T>(tuple: T, index: K): T[K];
    /**
     * Returns the first element of a Tuple.
     * @param tuple - the source tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.first(t))
     * // => 1
     * ```
     */
    function first<T extends Tuple.Source>(tuple: T): T[0];
    /**
     * Returns the second element of a Tuple.
     * @param tuple - the source tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.second(t))
     * // => 'a'
     * ```
     */
    function second<T extends Tuple.Source>(tuple: T): T[1];
    /**
     * Returns the last element of a Tuple.
     * @param tuple - the source tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.last(t))
     * // => true
     * ```
     */
    function last<T extends readonly unknown[], R>(tuple: readonly [...T, R]): R;
    /**
     * Returns a copy of the given `tuple` where the element at given `index` is updated with the
     * given `updater`.
     * @param tuple - the source tuple
     * @param index - the index in the tuple
     * @param updater - the updater for the value
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.updateAt(t, 1, 'b'))
     * // => [1, 'b', true]
     * ```
     */
    function updateAt<T extends Tuple.Source, K extends keyof T = keyof T>(tuple: T, index: K, updater: Update<T[K]>): T;
    /**
     * Returns the given `tuple` with the given `values` appended.
     * @param tuple - the source tuple
     * @param values - the values to append
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a')
     * console.log(Tuple.append(t, true, 5))
     * // => [1, 'a', true, 5]
     * ```
     */
    function append<T extends Tuple.Source, V extends readonly [unknown, ...unknown[]]>(tuple: T, ...values: V): readonly [...T, ...V];
    /**
     * Returns a Tuple containing the elements of given `tuple1` followed by the elements
     * of given `tuple2`.
     * @param tuple1 - the first Tuple
     * @param tuple2 - the second Tuple
     * @example
     * ```ts
     * const t1 = Tuple.of(1, 'a')
     * const t2 = Tuple.of(true, 5)
     * console.log(Tuple.concat(t1, t2))
     * // => [1, 'a', true, 5]
     * ```
     */
    function concat<T1 extends Tuple.Source, T2 extends Tuple.Source>(tuple1: T1, tuple2: T2): readonly [...T1, ...T2];
    /**
     * Returns a Tuple containing all but the last element of the given `tuple`.
     * @param tuple - the source tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.init(t))
     * // => [1, 'a']
     * ```
     */
    function init<T extends readonly unknown[]>(tuple: readonly [...T, unknown]): Readonly<T>;
    /**
     * Returns a Tuple containing all but the first element of the given `tuple`.
     * @param tuple - the source tuple
     * @example
     * ```ts
     * const t = Tuple.of(1, 'a', true)
     * console.log(Tuple.tail(t))
     * // => ['a', true]
     * ```
     */
    function tail<T extends readonly [...unknown[]]>(tuple: readonly [unknown, ...T]): Readonly<T>;
}
