Skip to content

Commit

Permalink
fix: improve data package types
Browse files Browse the repository at this point in the history
This commit improves the types in the data package.

- Adds new types `ThunkArgs` and `Thunk`. These types are intended
  to be used by consumers of the data package to define their own
	thunks.
- Adds meta action creators to the `ActionCreatorsOf` type.
- Adds the `dispatch` and `select` functions to the `DataRegistry` type.
- Adds the `invalidate` action creators to the `ActionCreatorsOf` type.

This allows consumers of the data package to have more complete
type safety. Also, provides access to the invalidate resolution
action creators, which are useful for complex data store
manipulation.

Adding new types as described above.

Building the package types.
  • Loading branch information
johnhooks committed Sep 17, 2024
1 parent 636710b commit 68e510c
Showing 1 changed file with 94 additions and 3 deletions.
97 changes: 94 additions & 3 deletions packages/data/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
* External dependencies
*/
// eslint-disable-next-line no-restricted-imports
import type { combineReducers as reduxCombineReducers } from 'redux';
import type { combineReducers as reduxCombineReducers, AnyAction } from 'redux';

/**
* Internal dependencies
*/
import type {
invalidateResolution,
invalidateResolutionForStore,
invalidateResolutionForStoreSelector,
} from './redux-store/metadata/actions';

type MapOf< T > = { [ name: string ]: T };

Expand Down Expand Up @@ -43,6 +52,34 @@ export interface ReduxStoreConfig<
controls?: MapOf< Function >;
}

type InvalidateResolution = typeof invalidateResolution;
type InvalidateResolutionForStore = typeof invalidateResolutionForStore;
type InvalidateResolutionForStoreSelector =
typeof invalidateResolutionForStoreSelector;

type InvalidateResolutionAction = ReturnType< InvalidateResolution >;
type InvalidateResolutionForStoreAction =
ReturnType< InvalidateResolutionForStore >;
type InvalidateResolutionForStoreSelectorAction =
ReturnType< InvalidateResolutionForStoreSelector >;

/**
* The action creators for metadata actions.
*/
type MetadataActionCreators = {
invalidateResolution: InvalidateResolution;
invalidateResolutionForStore: InvalidateResolutionForStore;
invalidateResolutionForStoreSelector: InvalidateResolutionForStoreSelector;
};

/**
* Metadata actions.
*/
type MetadataAction =
| InvalidateResolutionAction
| InvalidateResolutionForStoreAction
| InvalidateResolutionForStoreSelectorAction;

// Return type for the useSelect() hook.
export type UseSelectReturn< F extends MapSelect | StoreDescriptor< any > > =
F extends MapSelect
Expand Down Expand Up @@ -158,7 +195,17 @@ export interface SelectorWithCustomCurrySignature {
}

export interface DataRegistry {
register: ( store: StoreDescriptor< any > ) => void;
register: ( store: StoreDescriptor< AnyConfig > ) => void;
dispatch: < S extends string | StoreDescriptor< AnyConfig > >(
storeNameOrDescriptor: S
) => S extends StoreDescriptor< infer Config >
? ActionCreatorsOf< Config >
: unknown;
select: < S extends string | StoreDescriptor< AnyConfig > >(
storeNameOrDescriptor: S
) => S extends StoreDescriptor< infer Config >
? CurriedSelectorsOf< Config >
: unknown;
}

export interface DataEmitter {
Expand All @@ -173,11 +220,19 @@ export interface DataEmitter {

export type ConfigOf< S > = S extends StoreDescriptor< infer C > ? C : never;

export type ActionCreatorsOf< Config extends AnyConfig > =
export type BaseActionCreatorsOf< Config extends AnyConfig > =
Config extends ReduxStoreConfig< any, infer ActionCreators, any >
? PromisifiedActionCreators< ActionCreators >
: never;

/**
* The action creators for a store config.
*
* Also includes metadata actions creators.
*/
type ActionCreatorsOf< Config extends AnyConfig > =
BaseActionCreatorsOf< Config > & MetadataActionCreators;

// Takes an object containing all action creators for a store and updates the
// return type of each action creator to account for internal registry details --
// for example, dispatched actions are wrapped with a Promise.
Expand Down Expand Up @@ -214,4 +269,40 @@ type SelectorsOf< Config extends AnyConfig > = Config extends ReduxStoreConfig<
? { [ name in keyof Selectors ]: Function }
: never;

/**
* Thunk arguments.
*
* Used to type the arguments passed to a thunk function.
*/
export type ThunkArgs<
Action extends AnyAction,
S extends StoreDescriptor< AnyConfig >,
> = {
/**
* Dispatch an action to the store.
*/
dispatch: ( S extends StoreDescriptor< infer Config >
? ActionCreatorsOf< Config >
: unknown ) &
( ( action: Action | MetadataAction ) => void );

/**
* Selectors for the store.
*/
select: CurriedSelectorsOf< S >;

/**
* The store registry object.
*/
registry: DataRegistry;
};

export type Thunk<
A extends AnyAction,
S extends StoreDescriptor< AnyConfig >,
T extends unknown = void,
> = T extends Awaited< infer R >
? ( args: ThunkArgs< A, S > ) => Promise< R >
: ( args: ThunkArgs< A, S > ) => T;

export type combineReducers = typeof reduxCombineReducers;

0 comments on commit 68e510c

Please sign in to comment.