Skip to content

Core Commands: Refactor to TypeScript - #84385

Open
kushagra-goyal-14 wants to merge 5 commits into
WordPress:trunkfrom
kushagra-goyal-14:typescript/core-commands
Open

kushagra-goyal-14 wants to merge 5 commits into
WordPress:trunkfrom
kushagra-goyal-14:typescript/core-commands

Conversation

@kushagra-goyal-14

Copy link
Copy Markdown
Contributor

What?

See #67691

Converts @wordpress/core-commands source files and its search-ordering tests to TypeScript, and adds native type declarations.

Why?

Provide typed command palette settings, navigation commands, and search results, with declarations generated from the package source.

How?

  • Renames six source files and the existing test file to .ts/.tsx, preserving existing comments and traceable Git history.
  • Adds shared types for command palette settings, admin menu commands, and searchable entity records.
  • Keeps private router contracts and the existing window property declaration separate from public types.
  • Types command loader hooks and command configurations using @wordpress/commands.
  • Makes the search-ordering utility generic, preserving the input record type.
  • Adds separate build and development TypeScript configs, dependency references, declaration exports, and an optional @types/react peer.
  • Updates generated API documentation and the package changelog.
  • Adds coverage for empty searches, case-insensitive ordering, missing titles, nonmutation, and invalid JavaScript inputs.

No runtime changes. Existing hooks and navigation behavior are preserved.

Testing Instructions

  1. Run npm run typecheck.
  2. Run npm run test:unit -- packages/core-commands.
  3. Run npm run build.
  4. Run npm run check:type-declarations.
  5. Run npm run lint:published-deps.
  6. Start local WordPress with npm run wp-env -- start.
  7. Open a saved post or page and open the Command Palette.
  8. Search for posts/pages and run available admin navigation commands, including “Go to: Posts > All Posts” and “View site”.
  9. In the Site Editor, search for templates/template parts and run available navigation commands.
  10. Check the browser console for errors.

Testing Instructions for Keyboard

  1. Open a saved post/page or the Site Editor.
  2. Press Cmd+K on macOS or Ctrl+K on Windows/Linux.
  3. Type a search, use arrow keys to select a result, and press Enter.
  4. Reopen the palette and press Escape to close it.

Use of AI Tools

Codex assisted with the TypeScript migration, review feedback analysis, tests, and validation.

@github-actions github-actions Bot added the [Package] Core commands /packages/core-commands label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

🎉 Props

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: kushagra-goyal-14 <kush123@git.wordpress.org>

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

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

@kushagra-goyal-14

Copy link
Copy Markdown
Contributor Author

Hi @manzoorwanijk let me know if you have some recommendations or have some thoughts regarding this.

@kushagra-goyal-14
kushagra-goyal-14 marked this pull request as ready for review October 9, 2026 15:03
@manzoorwanijk manzoorwanijk added the [Type] Code Quality Issues or PRs that relate to code quality label Oct 13, 2026
/**
* The router private APIs consumed by the command palette.
*/
export interface RouterPrivateApis {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This hand-written copy already drifts from the router: RouterProvider requires routes and matchResolverArgs, which index.tsx does not pass, so the mismatch is hidden rather than typed. core-data has a precedent: export type CoreDataPrivateApis = typeof lockedApis. Exporting a RouterPrivateApis type the same way from @wordpress/router (and making routes/matchResolverArgs optional there, since both are already handled when absent) would let this file drop the copy.

* The router private APIs consumed by the command palette.
*/
export interface RouterPrivateApis {
RouterProvider: React.ComponentType< {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

React.ComponentType/React.ReactNode resolve through the UMD global with no import, so lint:published-deps cannot see the dependency that the new @types/react peer is for. Prefer import type { ComponentType, ReactNode } from 'react';, like @wordpress/commands. If the router type suggestion above lands, this file (and possibly the peer) goes away.

const commands = useMemo< CommandConfig[] >( () => {
if (
! canCreateTemplate ||
// @ts-expect-error Preserve the existing boolean/string comparison during migration.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

! templateType === 'wp_template_part' is always false, so this classic-theme guard never applies. Keeping the behavior is right for this PR, but could you open a follow-up issue (likely intent: templateType !== 'wp_template_part') and reference it in this comment so the @ts-expect-error does not become permanent?

import { useAdminNavigationCommands } from './admin-navigation-commands';
import { useSiteEditorNavigationCommands } from './site-editor-navigation-commands';
import { unlock } from './lock-unlock';
import type { CommandPaletteSettings } from './types';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

CommandPaletteSettings is now the public parameter type of initializeCommandPalette, but consumers cannot import it. Consider export type { AdminMenuCommand, CommandPaletteSettings } from './types';.

/**
* The title fields used to prioritize entity search results.
*/
export interface SearchableEntityRecord {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

SearchableEntityRecord is only the internal constraint for orderEntityRecordsBySearch; it fits better in private-types.ts (or next to the util) than in the public types file.

return ( records ?? [] ).map( ( record ) => {
const command = {
const commands = useMemo< CommandConfig[] >( () => {
return ( records ?? [] ).map< CommandConfig >( ( record ) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: the template loader types its records with getEntityRecords< WpTemplate | WpTemplatePart >, but this loader's getEntityRecords call (line 125) is untyped. getEntityRecords< Post | Page > from @wordpress/core-data would keep them consistent.

Comment on lines +108 to +109
// @ts-expect-error JavaScript callers can pass values outside the typed contract.
expect( orderEntityRecordsBySearch( {} ) ).toEqual( [] );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let us narrow this suppression down to the point where it applies. See my blog post about it - https://manzoorwani.dev/youre-probably-using-ts-expect-error-wrong/

This branch has not been deployed

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

Labels

[Package] Core commands /packages/core-commands [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants