/**
 * Copyright (C) 2019-present, Rimeto, LLC.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
/**
 * A generic type that cannot be `undefined`.
 */
export declare type Defined<T> = Exclude<T, undefined>;
/**
 * `PropChainObjectWrapper` gives TypeScript visibility into the properties of
 * an `PropChainType` object at compile-time.
 */
export declare type PropChainObjectWrapper<S, T> = {
    [K in keyof T]-?: PropChainType<S, T[K]>;
};
/**
 * Data accessor interface to dereference the value of the `TSOCType`.
 */
export interface PropChainDataAccessor<S, T> {
    /**
     * Data accessor without a default value. If no data exists,
     * `undefined` is returned.
     */
    <Callback extends PropChainCallback<S, T>>(callback: Callback): PropChainOnFinish<S, T, Callback>;
}
/**
 * `PropChainArrayWrapper` gives TypeScript visibility into the `PropChainType` 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 PropChainArrayWrapper<S, T extends PropChainCallback<S, T | number>> {
    length: PropChainType<S, number>;
    [K: number]: PropChainType<S, T>;
}
/**
 * Data accessor interface to dereference the value of an `any` type.
 * @extends PropChainDataAccessor<any>
 */
export interface PropChainAny<S> extends PropChainDataAccessor<S, any> {
    [K: string]: PropChainAny<S>;
}
/**
 * `PropChainDataWrapper` selects between `PropChainArrayWrapper`, `PropChainObjectWrapper`, and `PropChainDataAccessor`
 * to wrap Arrays, Objects and all other types respectively.
 */
export declare type PropChainDataWrapper<S, T> = 0 extends 1 & T ? PropChainAny<S> & PropChainDataAccessor<S, T> : T extends any[] ? PropChainArrayWrapper<S, T[number]> : T extends object ? PropChainObjectWrapper<S, T> : PropChainDataAccessor<S, T>;
/**
 * An object that supports optional chaining
 */
export declare type PropChainType<S, T> = PropChainDataAccessor<S, T> & PropChainDataWrapper<S, NonNullable<T>>;
export declare type PropChainCallback<S, T> = (getter: (state: S) => T, keyPath: Array<string | number>) => any;
/**
 * Callback returned by prop-chain
 */
export declare type PropChainOnFinish<S, T, Callback extends PropChainCallback<S, T>> = ReturnType<Callback> extends (...args: infer P) => infer R ? (...args: P) => R : never;
export declare function continuePropertyChain<S, T, Callback, DataAccessor>(state: S, data: T, keyPath?: Array<string | number>): PropChainType<S, T>;
/**
 * Start a new prop chain of the type specified
 *
 * @param state
 */
export declare function propertyChain<S>(state?: S): PropChainType<S, S>;
