Skip to content

Conversation

@joshualip-plaudit
Copy link
Contributor

@joshualip-plaudit joshualip-plaudit commented Jan 9, 2026

What?

Closes #74475

This PR adds the necessary types to access the redux store in the preferences package by name.

Why?

It's a nice convenience feature.

How?

See above

Testing Instructions

I don't actually know how to test compile-time-only stuff in this repo. DefinitelyTyped has a whole system set up for testing compile-time-only types, but I didn't see anything about that here.

@github-actions
Copy link

github-actions bot commented Jan 9, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: joshualip-plaudit <[email protected]>
Co-authored-by: manzoorwanijk <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds TypeScript type definitions to enable type-safe access to the preferences Redux store when using @wordpress/data functions with the store name string 'core/preferences'. The changes implement module augmentation to provide autocomplete and type checking for dispatch actions and selectors.

  • Adds module augmentation for @wordpress/data to type the preferences store access
  • Creates helper types to curry selector signatures (removing the state parameter)
  • Updates CHANGELOG to document the new TypeScript support

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
packages/preferences/src/store/index.ts Adds TypeScript module augmentation for @wordpress/data with type definitions for dispatch, select, useDispatch, and useSelect when used with the preferences store name
packages/preferences/CHANGELOG.md Documents the addition of TypeScript types for store access

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +46

type SubsequentArgsOfFunc< F > = F extends ( arg: any, ...args: infer R ) => any
? R
: never;
type CurriedSelectors = {
[ key in keyof typeof selectors ]: (
...args: SubsequentArgsOfFunc< ( typeof selectors )[ key ] >
) => ReturnType< ( typeof selectors )[ key ] >;
};
declare module '@wordpress/data' {
function dispatch( key: typeof STORE_NAME ): typeof actions;
function select( key: typeof STORE_NAME ): CurriedSelectors;

function useDispatch( key: typeof STORE_NAME ): typeof actions;
function useSelect( key: typeof STORE_NAME ): CurriedSelectors;
}
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

This module augmentation pattern may not work as intended in TypeScript. When augmenting a module that exports functions using 'export function', adding 'declare function' overloads in the augmentation doesn't reliably create merged overloads - the behavior depends on the TypeScript version and module resolution settings.

The recommended approach for type-safe store access is to use the store descriptor object directly (the exported 'store' constant) rather than string names, as this is how the '@wordpress/data' types are designed to work. If string-based access with types is required, the '@wordpress/data' package would need to expose these functions through an interface or namespace that can be properly augmented.

You may want to verify this augmentation works correctly across different TypeScript configurations and versions before merging.

Suggested change
type SubsequentArgsOfFunc< F > = F extends ( arg: any, ...args: infer R ) => any
? R
: never;
type CurriedSelectors = {
[ key in keyof typeof selectors ]: (
...args: SubsequentArgsOfFunc< ( typeof selectors )[ key ] >
) => ReturnType< ( typeof selectors )[ key ] >;
};
declare module '@wordpress/data' {
function dispatch( key: typeof STORE_NAME ): typeof actions;
function select( key: typeof STORE_NAME ): CurriedSelectors;
function useDispatch( key: typeof STORE_NAME ): typeof actions;
function useSelect( key: typeof STORE_NAME ): CurriedSelectors;
}

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +38
type SubsequentArgsOfFunc< F > = F extends ( arg: any, ...args: infer R ) => any
? R
: never;
type CurriedSelectors = {
[ key in keyof typeof selectors ]: (
...args: SubsequentArgsOfFunc< ( typeof selectors )[ key ] >
) => ReturnType< ( typeof selectors )[ key ] >;
Copy link

Copilot AI Jan 9, 2026

Choose a reason for hiding this comment

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

The SubsequentArgsOfFunc type helper is reinventing functionality that already exists in '@wordpress/data'. The CurriedState type in packages/data/src/types.ts (lines 146-150) provides the same functionality for currying selectors by removing the first state argument.

Consider using the built-in CurriedState type or CurriedSelectorsOf type from '@wordpress/data' instead of creating a custom implementation to maintain consistency with the framework's type system.

Copilot uses AI. Check for mistakes.
@manzoorwanijk
Copy link
Member

manzoorwanijk commented Jan 9, 2026

It's not encouraged to use the store name for such use-cases. It's recommended to use the store object instead to use the types automatically.

import { store as preferencesStore } from '@wordpress/preferences';

const data = useSelect( select => {
    return select( preferencesStore ).get( 'scope', 'name' );
} );

Using the import also sets the correct dependencies for your application to avoid missing or unknown dependencies for uses outside the block editor.

I recently wrote a blog post about how to use it with type-checking

Why @wordpress/preferences is the Best-Kept Secret for Storing User Preferences in the Block Editor

@joshualip-plaudit
Copy link
Contributor Author

@manzoorwanijk Good to know. Should I mark this as closed?

@manzoorwanijk
Copy link
Member

Should I mark this as closed?

Yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Preferences /packages/preferences [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add the necessary types to reference the preferences redux store by name

3 participants