/**
 * External dependencies
 */
import type { combineReducers as reduxCombineReducers } from 'redux';
type MapOf<T> = {
    [name: string]: T;
};
export type ActionCreator = (...args: any[]) => any | Generator;
export type Resolver = Function | Generator;
export type Selector = Function;
export type AnyConfig = ReduxStoreConfig<any, any, any>;
export interface StoreInstance<Config extends AnyConfig> {
    getSelectors: () => SelectorsOf<Config>;
    getActions: () => ActionCreatorsOf<Config>;
    subscribe: (listener: () => void) => () => void;
}
export interface StoreDescriptor<Config extends AnyConfig = AnyConfig> {
    /**
     * Store Name
     */
    name: string;
    /**
     * Creates a store instance
     */
    instantiate: (registry: DataRegistry) => StoreInstance<Config>;
}
export interface ReduxStoreConfig<State, ActionCreators extends MapOf<ActionCreator>, Selectors> {
    initialState?: State;
    reducer: (state: any, action: any) => any;
    actions?: ActionCreators;
    resolvers?: MapOf<Resolver>;
    selectors?: Selectors;
    controls?: MapOf<Function>;
}
export type UseSelectReturn<F extends MapSelect | StoreDescriptor<any>> = F extends MapSelect ? ReturnType<F> : F extends StoreDescriptor<any> ? CurriedSelectorsOf<F> : never;
export type UseDispatchReturn<StoreNameOrDescriptor> = StoreNameOrDescriptor extends StoreDescriptor<any> ? ActionCreatorsOf<ConfigOf<StoreNameOrDescriptor>> : StoreNameOrDescriptor extends undefined ? DispatchFunction : any;
export type DispatchFunction = <StoreNameOrDescriptor>(store: StoreNameOrDescriptor) => DispatchReturn<StoreNameOrDescriptor>;
export type DispatchReturn<StoreNameOrDescriptor> = StoreNameOrDescriptor extends StoreDescriptor<any> ? ActionCreatorsOf<ConfigOf<StoreNameOrDescriptor>> : unknown;
export type MapSelect = (select: SelectFunction, registry: DataRegistry) => any;
export type SelectFunction = <S>(store: S) => CurriedSelectorsOf<S>;
/**
 * Callback for store's `subscribe()` method that
 * runs when the store data has changed.
 */
export type ListenerFunction = () => void;
export type CurriedSelectorsOf<S> = S extends StoreDescriptor<ReduxStoreConfig<any, any, infer Selectors>> ? {
    [key in keyof Selectors]: CurriedState<Selectors[key]>;
} : never;
/**
 * Like CurriedState but wraps the return type in a Promise.
 * Used for resolveSelect where selectors return promises.
 *
 * For generic selectors that define PromiseCurriedSignature, that signature
 * is used directly to preserve generic type parameters (which would otherwise
 * be lost when using `infer`).
 */
type CurriedStateWithPromise<F> = F extends SelectorWithCustomCurrySignature & {
    PromiseCurriedSignature: infer S;
} ? S : F extends SelectorWithCustomCurrySignature & {
    CurriedSignature: (...args: infer P) => infer R;
} ? (...args: P) => Promise<R> : F extends (state: any, ...args: infer P) => infer R ? (...args: P) => Promise<R> : F;
/**
 * Like CurriedSelectorsOf but each selector returns a Promise.
 * Used for resolveSelect.
 */
export type CurriedSelectorsResolveOf<S> = S extends StoreDescriptor<ReduxStoreConfig<any, any, infer Selectors>> ? {
    [key in keyof Selectors]: CurriedStateWithPromise<Selectors[key]>;
} : never;
/**
 * Removes the first argument from a function.
 *
 * By default, it removes the `state` parameter from
 * registered selectors since that argument is supplied
 * by the editor when calling `select(…)`.
 *
 * For functions with no arguments, which some selectors
 * are free to define, returns the original function.
 *
 * It is possible to manually provide a custom curried signature
 * and avoid the automatic inference. When the
 * F generic argument passed to this helper extends the
 * SelectorWithCustomCurrySignature type, the F['CurriedSignature']
 * property is used verbatim.
 *
 * This is useful because TypeScript does not correctly remove
 * arguments from complex function signatures constrained by
 * interdependent generic parameters.
 * For more context, see https://github.com/WordPress/gutenberg/pull/41578
 */
type CurriedState<F> = F extends SelectorWithCustomCurrySignature ? F['CurriedSignature'] : F extends (state: any, ...args: infer P) => infer R ? (...args: P) => R : F;
/**
 * Utility to manually specify curried selector signatures.
 *
 * It comes handy when TypeScript can't automatically produce the
 * correct curried function signature. For example:
 *
 * ```ts
 * type BadlyInferredSignature = CurriedState<
 *     <K extends string | number>(
 *         state: any,
 *         kind: K,
 *         key: K extends string ? 'one value' : false
 *     ) => K
 * >
 * // BadlyInferredSignature evaluates to:
 * // (kind: string number, key: false "one value") => string number
 * ```
 *
 * With SelectorWithCustomCurrySignature, we can provide a custom
 * signature and avoid relying on TypeScript inference:
 * ```ts
 * interface MySelectorSignature extends SelectorWithCustomCurrySignature {
 *     <K extends string | number>(
 *         state: any,
 *         kind: K,
 *         key: K extends string ? 'one value' : false
 *     ): K;
 *
 *     CurriedSignature: <K extends string | number>(
 *         kind: K,
 *         key: K extends string ? 'one value' : false
 *     ): K;
 * }
 * type CorrectlyInferredSignature = CurriedState<MySelectorSignature>
 * // <K extends string | number>(kind: K, key: K extends string ? 'one value' : false): K;
 *
 * For even more context, see https://github.com/WordPress/gutenberg/pull/41578
 * ```
 */
export interface SelectorWithCustomCurrySignature {
    CurriedSignature: Function;
    PromiseCurriedSignature?: Function;
}
export interface DataRegistry {
    register: (store: StoreDescriptor<any>) => void;
    dispatch: <S extends StoreDescriptor<any>>(store: S) => ActionCreatorsOf<ConfigOf<S>>;
}
export type ConfigOf<S> = S extends StoreDescriptor<infer C> ? C : never;
export type ActionCreatorsOf<Config extends AnyConfig> = Config extends ReduxStoreConfig<any, infer ActionCreators, any> ? PromisifiedActionCreators<ActionCreators> : never;
export type PromisifiedActionCreators<ActionCreators extends MapOf<ActionCreator>> = {
    [Action in keyof ActionCreators]: PromisifyActionCreator<ActionCreators[Action]>;
};
export type PromisifyActionCreator<Action extends ActionCreator> = (...args: Parameters<Action>) => Promise<ReturnType<Action> extends (..._args: any[]) => any ? ThunkReturnType<Action> : ReturnType<Action>>;
export type ThunkReturnType<Action extends ActionCreator> = Awaited<ReturnType<ReturnType<Action>>>;
type SelectorsOf<Config extends AnyConfig> = Config extends ReduxStoreConfig<any, any, infer Selectors> ? {
    [name in keyof Selectors]: Function;
} : never;
export type combineReducers = typeof reduxCombineReducers;
export {};
//# sourceMappingURL=types.d.ts.map