Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript: Convert factory utils in data package to TS #66746

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/core-data/src/private-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ export const getBlockPatternsForPostType = createRegistrySelector(
*/
export const getEntityRecordsPermissions = createRegistrySelector( ( select ) =>
createSelector(
( state: State, kind: string, name: string, ids: string[] ) => {
(
state: State,
kind: string,
name: string,
ids: string | string[]
) => {
Comment on lines -59 to +64
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The types for createRegistrySelector caught this error.

const normalizedIds = Array.isArray( ids ) ? ids : [ ids ];
return normalizedIds.map( ( id ) => ( {
delete: select( STORE_NAME ).canUser( 'delete', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
*
* @see The documentation for the `rememo` package from which the `createSelector` function is reexported.
*
* @param {Function} selector Selector function that calculates a value from state and parameters.
* @param {Function} getDependants Function that returns an array of "dependant" objects.
* @return {Function} A memoized version of `selector` that caches the calculated return values.
* @param selector Selector function that calculates a value from state and parameters.
* @param getDependants Function that returns an array of "dependant" objects.
* @return A memoized version of `selector` that caches the calculated return values.
*/
export { default as createSelector } from 'rememo';
35 changes: 24 additions & 11 deletions packages/data/src/factory.js → packages/data/src/factory.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* Internal dependencies
*/
import type { select as globalSelect } from './select';

/**
* Creates a selector function that takes additional curried argument with the
* registry `select` function. While a regular selector has signature
Expand Down Expand Up @@ -33,17 +38,25 @@
* registry as argument. The registry binding happens automatically when registering the selector
* with a store.
*
* @param {Function} registrySelector Function receiving a registry `select`
* function and returning a state selector.
* @param registrySelector Function receiving a registry `select`
* function and returning a state selector.
*
* @return {Function} Registry selector that can be registered with a store.
* @return Registry selector that can be registered with a store.
*/
export function createRegistrySelector( registrySelector ) {
export function createRegistrySelector<
Selector extends ( ...args: any[] ) => any,
>( registrySelector: ( select: typeof globalSelect ) => Selector ): Selector {
type WrappedSelector = {
( ...args: Parameters< Selector > ): ReturnType< Selector >;
isRegistrySelector: boolean;
registry?: any;
};

const selectorsByRegistry = new WeakMap();
// Create a selector function that is bound to the registry referenced by `selector.registry`
// and that has the same API as a regular selector. Binding it in such a way makes it
// possible to call the selector directly from another selector.
const wrappedSelector = ( ...args ) => {
const wrappedSelector: WrappedSelector = ( ...args ) => {
let selector = selectorsByRegistry.get( wrappedSelector.registry );
// We want to make sure the cache persists even when new registry
// instances are created. For example patterns create their own editors
Expand All @@ -60,12 +73,10 @@ export function createRegistrySelector( registrySelector ) {
* Flag indicating that the selector is a registry selector that needs the correct registry
* reference to be assigned to `selector.registry` to make it work correctly.
* be mapped as a registry selector.
*
* @type {boolean}
*/
wrappedSelector.isRegistrySelector = true;

return wrappedSelector;
return wrappedSelector as unknown as Selector;
}

/**
Expand All @@ -84,11 +95,13 @@ export function createRegistrySelector( registrySelector ) {
* When registering a control created with `createRegistryControl` with a store, the store
* knows which calling convention to use when executing the control.
*
* @param {Function} registryControl Function receiving a registry object and returning a control.
* @param registryControl Function receiving a registry object and returning a control.
*
* @return {Function} Registry control that can be registered with a store.
* @return Registry control that can be registered with a store.
*/
export function createRegistryControl( registryControl ) {
export function createRegistryControl< T extends ( ...args: any ) => any >(
registryControl: T & { isRegistryControl?: boolean }
) {
registryControl.isRegistryControl = true;

return registryControl;
Expand Down
Loading