/** * External dependencies */ import type { combineReducers as reduxCombineReducers, Store as ReduxStore } from 'redux'; /** * Internal dependencies */ import type { DataEmitter } from './utils/emitter'; import type { MetadataSelectors, MetadataActions } from './redux-store/metadata/types'; type MapOf = { [name: string]: T; }; export type ActionCreator = (...args: any[]) => any | Generator; export type Resolver = Function | Generator; export type Selector = Function; export type AnyConfig = ReduxStoreConfig; export interface StoreInstance { getSelectors: () => SelectorsOf; getActions: () => ActionCreatorsOf; subscribe: (listener: () => void) => () => void; } export interface StoreDescriptor { /** * Store Name */ name: string; /** * Creates a store instance */ instantiate: (registry: DataRegistry) => StoreInstance; } export interface ReduxStoreConfig { initialState?: State; reducer: (state: any, action: any) => any; actions?: ActionCreators; resolvers?: MapOf; selectors?: Selectors; controls?: MapOf; } export type UseSelectReturn> = F extends MapSelect ? ReturnType : F extends StoreDescriptor ? CurriedSelectorsOf : never; export type UseDispatchReturn = StoreNameOrDescriptor extends StoreDescriptor ? ActionCreatorsOf : StoreNameOrDescriptor extends undefined ? DispatchFunction : any; export type DispatchFunction = (store: StoreNameOrDescriptor) => DispatchReturn; export type DispatchReturn = StoreNameOrDescriptor extends StoreDescriptor ? ActionCreatorsOf : unknown; export type MapSelect = (select: SelectFunction, registry: DataRegistry) => any; export type SelectFunction = (store: S) => CurriedSelectorsOf; /** * Callback for store's `subscribe()` method that * runs when the store data has changed. */ export type ListenerFunction = () => void; export type CurriedSelectorsOf = S extends StoreDescriptor> ? { [key in keyof Selectors]: CurriedState; } & MetadataSelectors : 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 extends SelectorWithCustomCurrySignature & { PromiseCurriedSignature: infer S; } ? S : F extends SelectorWithCustomCurrySignature & { CurriedSignature: (...args: infer P) => infer R; } ? (...args: P) => Promise : F extends (state: any, ...args: infer P) => infer R ? (...args: P) => Promise : F; /** * Like CurriedSelectorsOf but each selector returns a Promise. * Used for resolveSelect. */ export type CurriedSelectorsResolveOf = S extends StoreDescriptor> ? { [key in keyof Selectors]: CurriedStateWithPromise; } : 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 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< * ( * 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 { * ( * state: any, * kind: K, * key: K extends string ? 'one value' : false * ): K; * * CurriedSignature: ( * kind: K, * key: K extends string ? 'one value' : false * ): K; * } * type CorrectlyInferredSignature = CurriedState * // (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; } /** * A store name or store descriptor, used throughout the API. */ export type StoreNameOrDescriptor = string | StoreDescriptor; /** * An isolated orchestrator of store registrations. * * Returned by `createRegistry`. Provides methods to register stores, * select data, dispatch actions, and subscribe to changes. */ export interface DataRegistry { batch: (callback: () => void) => void; stores: Record; namespaces: Record; subscribe: (listener: ListenerFunction, storeNameOrDescriptor?: StoreNameOrDescriptor) => () => void; select: { >(store: S): CurriedSelectorsOf; (store: StoreNameOrDescriptor): Record any>; }; resolveSelect: { >(store: S): CurriedSelectorsResolveOf; (store: StoreNameOrDescriptor): Record Promise>; }; suspendSelect: { >(store: S): CurriedSelectorsOf; (store: StoreNameOrDescriptor): Record any>; }; dispatch: { >(store: S): ActionCreatorsOf; (store: StoreNameOrDescriptor): Record any>; }; use: (plugin: DataPlugin, options?: Record) => DataRegistry; register: (store: StoreDescriptor) => void; registerGenericStore: (name: string, store: StoreInstance) => void; registerStore: (storeName: string, options: ReduxStoreConfig) => ReduxStore; __unstableMarkListeningStores: (callback: () => T, ref: { current: string[] | null; }) => T; } /** * The plugin function signature. */ export type DataPlugin = (registry: DataRegistry, options?: Record) => Partial; /** * Status of a selector resolution. */ export type ResolutionStatus = 'resolving' | 'finished' | 'error'; /** * State value for a single resolution. */ export type ResolutionState = { status: 'resolving'; } | { status: 'finished'; } | { status: 'error'; error: Error | unknown; }; /** * A normalized resolver with a `fulfill` method and optional `isFulfilled`. */ export interface NormalizedResolver { /** * The function to call to fulfill the resolver. */ fulfill: (...args: any[]) => any; /** * Optional function to check if the resolver is already fulfilled. */ isFulfilled?: (state: any, ...args: any[]) => boolean; /** * Optional function to check if the resolver should be invalidated. */ shouldInvalidate?: (action: any, ...args: any[]) => boolean; } /** * A bound selector with optional resolver metadata. */ export interface BoundSelector { (...args: any[]): any; /** * Whether this selector has a resolver attached. */ hasResolver: boolean; /** * Optional function to normalize the arguments. */ __unstableNormalizeArgs?: (args: any[]) => any[]; /** * Whether this selector is a registry selector. */ isRegistrySelector?: boolean; /** * The registry instance this selector is bound to. */ registry?: DataRegistry; } /** * The shape of a store instance as seen internally by the registry. * Extends the public StoreInstance with additional internal properties. */ export interface InternalStoreInstance extends StoreInstance { /** * The Redux store instance (only for Redux-based stores). */ store?: ReduxStore; /** * The internal emitter for pause/resume batching. */ emitter: DataEmitter; /** * The combined reducer. */ reducer?: (state: any, action: any) => any; /** * Bound actions object. */ actions?: Record; /** * Bound selectors object. */ selectors?: Record; /** * Resolver definitions. */ resolvers?: Record; /** * Returns resolve-wrapped selectors. */ getResolveSelectors?: () => Record Promise>; /** * Returns suspense-wrapped selectors. */ getSuspendSelectors?: () => Record any>; } /** * Control descriptor for the controls system. */ export interface ControlDescriptor { /** * The type of the control action. */ type: string; /** * The store key to target. */ storeKey: string; /** * The name of the selector (for select/resolveSelect controls). */ selectorName?: string; /** * The name of the action (for dispatch controls). */ actionName?: string; /** * Arguments for the selector or action. */ args: any[]; } /** * Storage interface (Web Storage API subset). */ export interface StorageInterface { getItem: (key: string) => string | null; setItem: (key: string, value: string) => void; removeItem?: (key: string) => void; clear?: VoidFunction; } export type ConfigOf = S extends StoreDescriptor ? C : never; export type ActionCreatorsOf = T extends StoreDescriptor> ? PromisifiedActionCreators & MetadataActions : T extends ReduxStoreConfig ? PromisifiedActionCreators : never; export type PromisifiedActionCreators = { [Action in keyof ActionCreators]: ActionCreators[Action] extends ActionCreator ? PromisifyActionCreator : ActionCreators[Action]; }; export type PromisifyActionCreator = (...args: Parameters) => Promise extends (..._args: any[]) => any ? ThunkReturnType : ReturnType extends Generator ? TReturn : ReturnType>; export type ThunkReturnType = Awaited>>; type SelectorsOf = Config extends ReduxStoreConfig ? { [name in keyof Selectors]: Function; } : never; /** * The argument object passed to every thunk function. When parameterized with * a store descriptor, `dispatch`, `select`, and `resolveSelect` are fully * typed against that store's actions and selectors. * * @example * ```ts * const myAction = * ( id: number ) => * async ( { dispatch, select }: ThunkArgs< typeof myStore > ) => { * const record = select.getRecord( id ); * dispatch.setLoading( true ); * }; * ``` */ export interface ThunkArgs = {}, PrivateActions extends Record = {}> { dispatch: ActionCreatorsOf & PromisifiedActionCreators & { (thunk: (...args: any[]) => R): R; (action: Record): unknown; }; select: CurriedSelectorsOf & { [key in keyof PrivateSelectors]: CurriedState; }; resolveSelect: CurriedSelectorsResolveOf; registry: DataRegistry; } export type combineReducers = typeof reduxCombineReducers; export {}; //# sourceMappingURL=types.d.ts.map