UNPKG

@wordpress/data

Version:
179 lines (156 loc) 5.22 kB
/** * External dependencies */ // eslint-disable-next-line no-restricted-imports import type { combineReducers as reduxCombineReducers } from 'redux'; type MapOf< T > = { [ name: string ]: T }; export type ActionCreator = Function | 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 > { /** * 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 ) => StoreNameOrDescriptor extends StoreDescriptor< any > ? ActionCreatorsOf< ConfigOf< StoreNameOrDescriptor > > : any; export type MapSelect = ( select: SelectFunction, registry: DataRegistry ) => any; export type SelectFunction = < S >( store: S ) => CurriedSelectorsOf< S >; export type CurriedSelectorsOf< S > = S extends StoreDescriptor< ReduxStoreConfig< any, any, infer Selectors > > ? { [ key in keyof Selectors ]: CurriedState< 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; } export interface DataRegistry { register: ( store: StoreDescriptor< any > ) => void; } export interface DataEmitter { emit: () => void; subscribe: ( listener: () => void ) => () => void; pause: () => void; resume: () => void; isPaused: boolean; } // Type Helpers. export type ConfigOf< S > = S extends StoreDescriptor< infer C > ? C : never; export type ActionCreatorsOf< Config extends AnyConfig > = Config extends ReduxStoreConfig< any, infer ActionCreators, any > ? ActionCreators : never; type SelectorsOf< Config extends AnyConfig > = Config extends ReduxStoreConfig< any, any, infer Selectors > ? { [ name in keyof Selectors ]: Function } : never; export type combineReducers = typeof reduxCombineReducers;