import type { State } from "../reducers";
import type { Selector } from "./SelectorTypes";
import type { ObservableStore } from "../store/ObservableStore";
/**
 * `SelectorChainObjectWrapper` gives TypeScript visibility into the properties of
 * an `SelectorChainType` object at compile-time.
 */
declare type SelectorChainObjectWrapper<S, T> = {
    [K in keyof T]-?: SelectorChainType<S, T[K]>;
};
/**
 * Data accessor interface to dereference the value of the `TSOCType`.
 */
/**
 * `SelectorChainArrayWrapper` gives TypeScript visibility into the `SelectorChainType` values of an array
 * without exposing Array methods (it is problematic to attempt to invoke methods during
 * the course of an optional chain traversal).
 */
export interface SelectorChainArrayWrapper<S, T extends SelectorChainCallback<S, T | number>> {
    length: SelectorChainType<S, number>;
    [K: number]: SelectorChainType<S, T>;
}
/**
 * Data accessor interface to dereference the value of an `any` type.
 * @extends SelectorChainDataAccessor<any>
 */
export interface SelectorChainAny<S> extends SelectorChainDataAccessor<S, S> {
    [K: string]: SelectorChainAny<S>;
}
/**
 * `SelectorChainDataWrapper` selects between `SelectorChainArrayWrapper`, `SelectorChainObjectWrapper`, and `SelectorChainDataAccessor`
 * to wrap Arrays, Objects and all other types respectively.
 */
export declare type SelectorChainDataWrapper<S, T> = 0 extends (1 & T) ? (SelectorChainAny<S> & SelectorChainDataAccessor<S, T>) : T extends any[] ? SelectorChainArrayWrapper<S, T[number]> : T extends object ? SelectorChainObjectWrapper<S, T> : SelectorChainDataAccessor<S, T>;
export declare type SelectorChainType<S, T> = (SelectorChainDataAccessor<S, T> & SelectorChainDataWrapper<S, NonNullable<T>>);
export declare type SelectorChainOnFinish<S, T, Callback extends SelectorChainCallback<S, T>> = ReturnType<Callback> extends ((...args: infer P) => (infer R)) ? ((...args: P) => R) : never;
export interface SelectorChainDataAccessor<S, T> {
    (): Selector<S, T>;
}
export interface SelectorChainCallback<S, T> {
    <T>(getter: (state: S) => T, keyPath: Array<string | number>): SelectorChainDataAccessor<S, T>;
}
export declare type SelectorChain<S> = SelectorChainType<S, S>;
export declare function selectorChain<S extends State>(store: ObservableStore<S>, state: S): SelectorChain<S>;
export {};
