From 4e239f882082471b0a0e0c5b204c489d29279245 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Wed, 12 Aug 2026 19:50:51 +0530 Subject: [PATCH 1/7] TypeScript: Require the typecheck run for type checking in CI With every package on the split layout, static-checks type checks through the typecheck script alone: the build step only bundles, and the type declaration check runs explicitly since --skip-types skips it. The docs drop the migration-in-progress wording. --- .github/workflows/static-checks.yml | 13 ++++++++----- AGENTS.md | 4 ++-- packages/README.md | 16 +++++----------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 583f4ee49546a2..6847a36aec39df 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -114,13 +114,16 @@ jobs: npm run lint:css -- --formatter compact npm run lint:css:update-suppressions - - name: Type check dev projects - # TODO: Fold the build type check below into this run once - # every package is migrated to the split tsconfig layout. + - name: Type checking run: npm run typecheck - - name: Type checking - run: npm run build + - name: Check type declaration files + # Runs against the declarations the type check just emitted; + # the bundle build below skips types and with them this check. + run: npm run --workspace @wordpress/build-scripts check-type-declarations + + - name: Build packages + run: npm run build -- --skip-types - name: Validate package contents run: npm run lint:package-contents diff --git a/AGENTS.md b/AGENTS.md index 13ebe7cdfe8190..b613abe6d231b8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,7 @@ Read only what your task needs, when it needs it: ```bash npm run format # Fix JS formatting npm run lint:js # Check JS linting -npm run typecheck # Type check sources, plus dev files of migrated packages +npm run typecheck # Type check everything, including tests and stories vendor/bin/phpcbf # Fix PHP standards vendor/bin/phpcs # Check PHP standards @@ -72,7 +72,7 @@ For full architecture details, see `docs/explanations/architecture/`. - Never invoke WordPress's forked or local CLIs through `npx` (e.g. `npx prettier`, `npx wp-scripts`). WordPress ships its own `wp-prettier` fork, and `wp-scripts` is the bin name of `@wordpress/scripts`. A bare `npx wp-scripts` can resolve to an unrelated third-party package on the public registry, not the local tool. Use the npm scripts instead (`npm run format`, `npm run lint:js`, `npm run lint:css` and so on), which run the binaries from local `node_modules`. - PHP function and class names are renamed at build time (`gutenberg_*` prefix, `*_Gutenberg` suffix) to avoid conflicts with WordPress Core — the built names, not the source names, are what runs (and what tests must call). See `docs/contributors/code/build-system-function-prefixing.md`. - Production code changes in a package require an entry in that package's `CHANGELOG.md`. See `docs/contributors/code/managing-packages.md`. -- TypeScript configs are being split per package, one package at a time: `tsconfig.build.json` (src only, emits `build-types`) and the default `tsconfig.json` (dev project: tests and stories, `noEmit`, jest types). References to a split package point at `..//tsconfig.build.json`, references to a package still on a single config point at `../`. `npm run build` does not type check the dev files of split packages; use `npm run typecheck` for those, and keep jest types out of build projects. See the TypeScript section in `packages/README.md`. +- TypeScript configs are split per package: `tsconfig.build.json` (src only, emits `build-types`) and the default `tsconfig.json` (dev project: tests and stories, `noEmit`, jest types). Cross-package references always point at `..//tsconfig.build.json`. `npm run build` never type checks dev files; use `npm run typecheck` for that, and never add jest types to a build project. See the TypeScript section in `packages/README.md`. - A rejected `apiFetch` is not always an `Error`: a REST error arrives as a plain object (`{ code, message, data }`), `parse: false` rejects with the `Response` (which carries `status`, not `message`), an aborted request rethrows an `AbortError`, and a handler set via `setFetchHandler` can reject anything. Do not interpolate the rejection into a string (`` `${ error }` `` gives `[object Object]`) or branch on `instanceof Error`. Normalise it to a message before showing the user anything, and supply your own copy when there is none — `ensureError` in `packages/core-data/src/private-actions.js` is the reference implementation, though it is local to that file rather than exported. ## PR instructions diff --git a/packages/README.md b/packages/README.md index e6c3cfe355bb2a..cab774d6596aef 100644 --- a/packages/README.md +++ b/packages/README.md @@ -327,9 +327,7 @@ Gutenberg uses TypeScript for several reasons, including: Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select packages. These packages benefit from type checking and produced type declarations in the published packages. -A package opts in to TypeScript tooling with a `tsconfig.json` in its root, registered in the root `tsconfig.build.json` references. - -Packages are being migrated to a two project layout, one package at a time: +A package opts in to TypeScript tooling with two tsconfig files: - `tsconfig.build.json` is the build project: it covers `src`, emits declarations to `build-types`, and is what other packages and `npm run build` consume. - `tsconfig.json` is the dev project: it covers test and story files with `noEmit`, so `npm run typecheck` and the IDE can check them without their declarations ending up in the published package. @@ -342,13 +340,9 @@ Both extend shared base configurations (comments are not necessary): // Extends a base configuration common to most packages. "extends": "../../tsconfig.base.json", - // Dependencies that have opted in to TypeScript are referenced here: a - // migrated one by its build project, one still on a single config by - // its directory. - "references": [ - { "path": "../dom-ready/tsconfig.build.json" }, - { "path": "../hooks" } - ] + // Dependencies that have opted in to TypeScript are referenced here, + // always by their build project. + "references": [ { "path": "../dom-ready/tsconfig.build.json" } ] } ``` @@ -364,7 +358,7 @@ Both extend shared base configurations (comments are not necessary): } ``` -A migrated package registers both projects at the root: `packages//tsconfig.build.json` in the root `tsconfig.build.json` references, and `packages/` in the root `tsconfig.json` references. +Register both projects at the root: `packages//tsconfig.build.json` in the root `tsconfig.build.json` references, and `packages/` in the root `tsconfig.json` references. Packages whose components feed the Storybook components manifest (`components`, `dataviews`, `ui`) carry a third project, `tsconfig.stories.json`, registered in the root `tsconfig.json` only. It type checks the stories against component sources without jest types. Storybook's component meta extractor reads props through the closest `tsconfig.json` that lists a story, or through its own inferred project when none does; the inferred project produces the complete manifest and the dev project does not, so stories stay out of `tsconfig.json`. The dev project cannot reference this one either, because a referenced project may not disable emit (TS6310), which is why it is registered at the root only. From 59bef3206c3e4ea76e8e7cf030383b54c9ad106c Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Wed, 12 Aug 2026 20:30:05 +0530 Subject: [PATCH 2/7] Docs: Keep the single-config shape for packages without dev files Thirty-odd packages have no test or story files and keep one build project referenced by directory, so the guidance shows both reference forms. --- AGENTS.md | 2 +- packages/README.md | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b613abe6d231b8..7a669bd8c7c1ff 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -72,7 +72,7 @@ For full architecture details, see `docs/explanations/architecture/`. - Never invoke WordPress's forked or local CLIs through `npx` (e.g. `npx prettier`, `npx wp-scripts`). WordPress ships its own `wp-prettier` fork, and `wp-scripts` is the bin name of `@wordpress/scripts`. A bare `npx wp-scripts` can resolve to an unrelated third-party package on the public registry, not the local tool. Use the npm scripts instead (`npm run format`, `npm run lint:js`, `npm run lint:css` and so on), which run the binaries from local `node_modules`. - PHP function and class names are renamed at build time (`gutenberg_*` prefix, `*_Gutenberg` suffix) to avoid conflicts with WordPress Core — the built names, not the source names, are what runs (and what tests must call). See `docs/contributors/code/build-system-function-prefixing.md`. - Production code changes in a package require an entry in that package's `CHANGELOG.md`. See `docs/contributors/code/managing-packages.md`. -- TypeScript configs are split per package: `tsconfig.build.json` (src only, emits `build-types`) and the default `tsconfig.json` (dev project: tests and stories, `noEmit`, jest types). Cross-package references always point at `..//tsconfig.build.json`. `npm run build` never type checks dev files; use `npm run typecheck` for that, and never add jest types to a build project. See the TypeScript section in `packages/README.md`. +- Packages with TypeScript dev files split their configs: `tsconfig.build.json` (src only, emits `build-types`) and the default `tsconfig.json` (dev project: tests and stories, `noEmit`, jest types). Packages without dev files keep a single `tsconfig.json` build project. Reference a split package by `..//tsconfig.build.json` and an unsplit one by `../`. `npm run build` never type checks dev files; use `npm run typecheck` for that, and never add jest types to a build project. See the TypeScript section in `packages/README.md`. - A rejected `apiFetch` is not always an `Error`: a REST error arrives as a plain object (`{ code, message, data }`), `parse: false` rejects with the `Response` (which carries `status`, not `message`), an aborted request rethrows an `AbortError`, and a handler set via `setFetchHandler` can reject anything. Do not interpolate the rejection into a string (`` `${ error }` `` gives `[object Object]`) or branch on `instanceof Error`. Normalise it to a message before showing the user anything, and supply your own copy when there is none — `ensureError` in `packages/core-data/src/private-actions.js` is the reference implementation, though it is local to that file rather than exported. ## PR instructions diff --git a/packages/README.md b/packages/README.md index cab774d6596aef..b8df58bd876ae5 100644 --- a/packages/README.md +++ b/packages/README.md @@ -327,7 +327,7 @@ Gutenberg uses TypeScript for several reasons, including: Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select packages. These packages benefit from type checking and produced type declarations in the published packages. -A package opts in to TypeScript tooling with two tsconfig files: +A package opts in to TypeScript tooling with a `tsconfig.json` build project registered in the root `tsconfig.build.json` references. Packages with test or story files split into two projects: - `tsconfig.build.json` is the build project: it covers `src`, emits declarations to `build-types`, and is what other packages and `npm run build` consume. - `tsconfig.json` is the dev project: it covers test and story files with `noEmit`, so `npm run typecheck` and the IDE can check them without their declarations ending up in the published package. @@ -340,9 +340,13 @@ Both extend shared base configurations (comments are not necessary): // Extends a base configuration common to most packages. "extends": "../../tsconfig.base.json", - // Dependencies that have opted in to TypeScript are referenced here, - // always by their build project. - "references": [ { "path": "../dom-ready/tsconfig.build.json" } ] + // Dependencies that have opted in to TypeScript are referenced here: a + // split one by its build project, one on a single config by its + // directory. + "references": [ + { "path": "../dom-ready/tsconfig.build.json" }, + { "path": "../hooks" } + ] } ``` From 8d56eadd9cb4f0a25f42a0caef3ad2d83e253c2d Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 17 Aug 2026 02:00:51 -0700 Subject: [PATCH 3/7] Split is-shallow-equal and style-runtime, whose tests live outside src Their TypeScript tests were checked by nothing: the base include only reaches src, so a single-config package cannot see them. Each gets a dev project rooted at the package, dependents point at the build projects, and the validator now fails any package that keeps TypeScript test or story files without a dev project. Two pre-existing test type errors are fixed instead of excluded. --- package-lock.json | 5 ++++ packages/admin-ui/tsconfig.build.json | 2 +- packages/admin-ui/tsconfig.json | 2 +- packages/block-editor/tsconfig.build.json | 2 +- packages/block-editor/tsconfig.json | 2 +- packages/blocks/tsconfig.json | 2 +- packages/components/CHANGELOG.md | 2 +- packages/components/tsconfig.build.json | 4 +-- packages/components/tsconfig.json | 4 +-- packages/components/tsconfig.stories.json | 4 +-- packages/compose/tsconfig.build.json | 2 +- packages/compose/tsconfig.json | 2 +- packages/core-data/tsconfig.build.json | 2 +- packages/core-data/tsconfig.json | 2 +- packages/data/tsconfig.json | 2 +- packages/grid/CHANGELOG.md | 2 +- packages/grid/tsconfig.build.json | 2 +- packages/grid/tsconfig.json | 2 +- packages/is-shallow-equal/CHANGELOG.md | 4 +++ packages/is-shallow-equal/package.json | 1 + packages/is-shallow-equal/test/index.ts | 2 +- packages/is-shallow-equal/tsconfig.build.json | 4 +++ packages/is-shallow-equal/tsconfig.json | 8 +++++- packages/plugins/tsconfig.json | 2 +- packages/style-runtime/CHANGELOG.md | 4 +++ packages/style-runtime/global.d.ts | 5 ++++ packages/style-runtime/package.json | 4 +++ packages/style-runtime/tsconfig.build.json | 4 +++ packages/style-runtime/tsconfig.json | 9 ++++++- packages/theme/CHANGELOG.md | 2 +- packages/theme/tsconfig.build.json | 2 +- packages/theme/tsconfig.json | 2 +- packages/ui/CHANGELOG.md | 2 +- packages/ui/tsconfig.build.json | 2 +- packages/ui/tsconfig.json | 2 +- packages/ui/tsconfig.stories.json | 2 +- packages/undo-manager/tsconfig.json | 2 +- packages/widget-dashboard/tsconfig.build.json | 2 +- packages/widget-dashboard/tsconfig.json | 2 +- packages/wp-build/tsconfig.json | 2 +- tools/validation/validate-tsconfig.mjs | 26 +++++++++++++++++++ tools/validation/validate-tsconfig.test.js | 17 ++++++++++++ tsconfig.build.json | 4 +-- tsconfig.json | 2 ++ 44 files changed, 126 insertions(+), 37 deletions(-) create mode 100644 packages/is-shallow-equal/tsconfig.build.json create mode 100644 packages/style-runtime/global.d.ts create mode 100644 packages/style-runtime/tsconfig.build.json diff --git a/package-lock.json b/package-lock.json index fdfed9a77121dd..1172cdcc8f2f59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53351,6 +53351,7 @@ "version": "5.53.0", "license": "GPL-2.0-or-later", "devDependencies": { + "@types/jest": "^30.0.0", "@wordpress/lazy-import": "file:../lazy-import", "benchmark": "^2.1.4" }, @@ -54926,6 +54927,10 @@ "name": "@wordpress/style-runtime", "version": "0.9.0", "license": "GPL-2.0-or-later", + "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@types/jest": "^30.0.0" + }, "engines": { "node": ">=20.10.0", "npm": ">=10.2.3" diff --git a/packages/admin-ui/tsconfig.build.json b/packages/admin-ui/tsconfig.build.json index ce7f9df496b991..f65ce7611db58e 100644 --- a/packages/admin-ui/tsconfig.build.json +++ b/packages/admin-ui/tsconfig.build.json @@ -10,7 +10,7 @@ { "path": "../i18n/tsconfig.build.json" }, { "path": "../private-apis" }, { "path": "../route" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" } ] } diff --git a/packages/admin-ui/tsconfig.json b/packages/admin-ui/tsconfig.json index 3d8f0ad68d0d92..ffe676a8bc0b55 100644 --- a/packages/admin-ui/tsconfig.json +++ b/packages/admin-ui/tsconfig.json @@ -12,7 +12,7 @@ { "path": "../i18n/tsconfig.build.json" }, { "path": "../private-apis" }, { "path": "../route" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" } ] } diff --git a/packages/block-editor/tsconfig.build.json b/packages/block-editor/tsconfig.build.json index 2dc2091c3cf71d..66cbbf35c23131 100644 --- a/packages/block-editor/tsconfig.build.json +++ b/packages/block-editor/tsconfig.build.json @@ -25,7 +25,7 @@ { "path": "../icons/tsconfig.build.json" }, { "path": "../image-cropper/tsconfig.build.json" }, { "path": "../interactivity/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../kebab-case" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../keyboard-shortcuts" }, diff --git a/packages/block-editor/tsconfig.json b/packages/block-editor/tsconfig.json index bf91587ef89876..2f491d9b055df2 100644 --- a/packages/block-editor/tsconfig.json +++ b/packages/block-editor/tsconfig.json @@ -29,7 +29,7 @@ { "path": "../icons/tsconfig.build.json" }, { "path": "../image-cropper/tsconfig.build.json" }, { "path": "../interactivity/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../kebab-case" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../keyboard-shortcuts" }, diff --git a/packages/blocks/tsconfig.json b/packages/blocks/tsconfig.json index 60c38b5c6cd0b4..5ef46b4d85d459 100644 --- a/packages/blocks/tsconfig.json +++ b/packages/blocks/tsconfig.json @@ -15,7 +15,7 @@ { "path": "../hooks" }, { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../private-apis" }, { "path": "../rich-text" }, diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 26ab6117d0fd50..43d734c6b72822 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -25,7 +25,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81516](https://github.com/WordPress/gutenberg/pull/81516)) +- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81516](https://github.com/WordPress/gutenberg/pull/81516), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81515](https://github.com/WordPress/gutenberg/pull/81515)) - Remove `ValidatedComboboxControl` from the private APIs; it now lives internally in `@wordpress/dataviews`, its only consumer ([#81449](https://github.com/WordPress/gutenberg/pull/81449)). - Remove `ValidatedFormTokenField` from the private APIs; it now lives internally in `@wordpress/dataviews`, its only consumer ([#81451](https://github.com/WordPress/gutenberg/pull/81451)). diff --git a/packages/components/tsconfig.build.json b/packages/components/tsconfig.build.json index 38e426796fafb5..538734fc4bb4eb 100644 --- a/packages/components/tsconfig.build.json +++ b/packages/components/tsconfig.build.json @@ -20,14 +20,14 @@ { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../kebab-case" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, { "path": "../react-i18n" }, { "path": "../rich-text" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" }, { "path": "../warning" } ] diff --git a/packages/components/tsconfig.json b/packages/components/tsconfig.json index df600cf92e7756..ccdd185e64ef98 100644 --- a/packages/components/tsconfig.json +++ b/packages/components/tsconfig.json @@ -32,14 +32,14 @@ { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../kebab-case" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, { "path": "../react-i18n" }, { "path": "../rich-text" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" }, { "path": "../warning" } ] diff --git a/packages/components/tsconfig.stories.json b/packages/components/tsconfig.stories.json index 1d62dc6a4e9f97..e53dc90fabbb95 100644 --- a/packages/components/tsconfig.stories.json +++ b/packages/components/tsconfig.stories.json @@ -36,14 +36,14 @@ { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../kebab-case" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, { "path": "../react-i18n" }, { "path": "../rich-text" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" }, { "path": "../warning" } ] diff --git a/packages/compose/tsconfig.build.json b/packages/compose/tsconfig.build.json index 571cda727699e8..1a99f65ba68859 100644 --- a/packages/compose/tsconfig.build.json +++ b/packages/compose/tsconfig.build.json @@ -8,7 +8,7 @@ { "path": "../deprecated/tsconfig.build.json" }, { "path": "../dom" }, { "path": "../element/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../priority-queue/tsconfig.build.json" }, { "path": "../private-apis" }, diff --git a/packages/compose/tsconfig.json b/packages/compose/tsconfig.json index 6ae3ff63e471a0..d171cdb0592966 100644 --- a/packages/compose/tsconfig.json +++ b/packages/compose/tsconfig.json @@ -9,7 +9,7 @@ { "path": "../deprecated/tsconfig.build.json" }, { "path": "../dom" }, { "path": "../element/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../keycodes/tsconfig.build.json" }, { "path": "../priority-queue/tsconfig.build.json" }, { "path": "../private-apis" }, diff --git a/packages/core-data/tsconfig.build.json b/packages/core-data/tsconfig.build.json index ab6b83da4bf44a..72d018d4bdddfa 100644 --- a/packages/core-data/tsconfig.build.json +++ b/packages/core-data/tsconfig.build.json @@ -19,7 +19,7 @@ { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../notices/tsconfig.build.json" }, { "path": "../private-apis" }, { "path": "../rich-text" }, diff --git a/packages/core-data/tsconfig.json b/packages/core-data/tsconfig.json index 88c4d74db0f8ae..298571aed4d266 100644 --- a/packages/core-data/tsconfig.json +++ b/packages/core-data/tsconfig.json @@ -18,7 +18,7 @@ { "path": "../html-entities/tsconfig.build.json" }, { "path": "../i18n/tsconfig.build.json" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../notices/tsconfig.build.json" }, { "path": "../private-apis" }, { "path": "../rich-text" }, diff --git a/packages/data/tsconfig.json b/packages/data/tsconfig.json index aa515ec8ebd5ef..6c5d80f536f367 100644 --- a/packages/data/tsconfig.json +++ b/packages/data/tsconfig.json @@ -9,7 +9,7 @@ { "path": "../deprecated/tsconfig.build.json" }, { "path": "../element/tsconfig.build.json" }, { "path": "../private-apis" }, - { "path": "../is-shallow-equal" }, + { "path": "../is-shallow-equal/tsconfig.build.json" }, { "path": "../priority-queue/tsconfig.build.json" }, { "path": "../redux-routine" } ] diff --git a/packages/grid/CHANGELOG.md b/packages/grid/CHANGELOG.md index 3c945203ae38d6..1a9d67ba499947 100644 --- a/packages/grid/CHANGELOG.md +++ b/packages/grid/CHANGELOG.md @@ -4,7 +4,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514)) +- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Split tsconfig into a build project and a default dev project; story and test declarations are no longer published to npm. ([#81509](https://github.com/WordPress/gutenberg/pull/81509)) ## 0.5.0 (2026-08-12) diff --git a/packages/grid/tsconfig.build.json b/packages/grid/tsconfig.build.json index 1cd55e9113e0e7..2e9b393061b5ae 100644 --- a/packages/grid/tsconfig.build.json +++ b/packages/grid/tsconfig.build.json @@ -7,6 +7,6 @@ "references": [ { "path": "../compose/tsconfig.build.json" }, { "path": "../element/tsconfig.build.json" }, - { "path": "../style-runtime" } + { "path": "../style-runtime/tsconfig.build.json" } ] } diff --git a/packages/grid/tsconfig.json b/packages/grid/tsconfig.json index e3e39ff06863b6..f2e7df7f1fd649 100644 --- a/packages/grid/tsconfig.json +++ b/packages/grid/tsconfig.json @@ -9,6 +9,6 @@ { "path": "./tsconfig.build.json" }, { "path": "../compose/tsconfig.build.json" }, { "path": "../element/tsconfig.build.json" }, - { "path": "../style-runtime" } + { "path": "../style-runtime/tsconfig.build.json" } ] } diff --git a/packages/is-shallow-equal/CHANGELOG.md b/packages/is-shallow-equal/CHANGELOG.md index 8e2161e6d0cc47..ba60371e284175 100644 --- a/packages/is-shallow-equal/CHANGELOG.md +++ b/packages/is-shallow-equal/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81518](https://github.com/WordPress/gutenberg/pull/81518)) + ## 5.53.0 (2026-08-12) diff --git a/packages/is-shallow-equal/package.json b/packages/is-shallow-equal/package.json index c1e13e88be985b..bc85f77bb70688 100644 --- a/packages/is-shallow-equal/package.json +++ b/packages/is-shallow-equal/package.json @@ -45,6 +45,7 @@ "types": "build-types", "sideEffects": false, "devDependencies": { + "@types/jest": "^30.0.0", "@wordpress/lazy-import": "file:../lazy-import", "benchmark": "^2.1.4" }, diff --git a/packages/is-shallow-equal/test/index.ts b/packages/is-shallow-equal/test/index.ts index 04aff5e523973c..cd5c12bdf920bf 100644 --- a/packages/is-shallow-equal/test/index.ts +++ b/packages/is-shallow-equal/test/index.ts @@ -146,7 +146,7 @@ describe( 'isShallowEqual', () => { } ); it( 'returns true on arrays that are a copy of each other', () => { - const a = []; + const a: unknown[] = []; const b = a; expect( isShallowEqual( a, b ) ).toBe( true ); diff --git a/packages/is-shallow-equal/tsconfig.build.json b/packages/is-shallow-equal/tsconfig.build.json new file mode 100644 index 00000000000000..7ff060ab6ce105 --- /dev/null +++ b/packages/is-shallow-equal/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json" +} diff --git a/packages/is-shallow-equal/tsconfig.json b/packages/is-shallow-equal/tsconfig.json index 7ff060ab6ce105..c339d20695cc3c 100644 --- a/packages/is-shallow-equal/tsconfig.json +++ b/packages/is-shallow-equal/tsconfig.json @@ -1,4 +1,10 @@ { "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.base.json" + "extends": "../../tsconfig.dev.base.json", + // Tests live beside src, not under it. + "compilerOptions": { + "rootDir": "." + }, + "include": [ "test/**/*.ts" ], + "references": [ { "path": "./tsconfig.build.json" } ] } diff --git a/packages/plugins/tsconfig.json b/packages/plugins/tsconfig.json index bea1787906d8a0..abe3ce0ff5ebfa 100644 --- a/packages/plugins/tsconfig.json +++ b/packages/plugins/tsconfig.json @@ -11,6 +11,6 @@ { "path": "../element/tsconfig.build.json" }, { "path": "../hooks" }, { "path": "../icons/tsconfig.build.json" }, - { "path": "../is-shallow-equal" } + { "path": "../is-shallow-equal/tsconfig.build.json" } ] } diff --git a/packages/style-runtime/CHANGELOG.md b/packages/style-runtime/CHANGELOG.md index e60013221c66f6..83ce913040d0cf 100644 --- a/packages/style-runtime/CHANGELOG.md +++ b/packages/style-runtime/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81518](https://github.com/WordPress/gutenberg/pull/81518)) + ## 0.9.0 (2026-08-12) diff --git a/packages/style-runtime/global.d.ts b/packages/style-runtime/global.d.ts new file mode 100644 index 00000000000000..c1289cbccb9928 --- /dev/null +++ b/packages/style-runtime/global.d.ts @@ -0,0 +1,5 @@ +/* + * With typeRoots set in tsconfig, global types outside those directories, + * like the jest-dom matchers, must be referenced explicitly. + */ +import '@testing-library/jest-dom'; diff --git a/packages/style-runtime/package.json b/packages/style-runtime/package.json index a540f843249c7f..d88e609c6ad5bc 100644 --- a/packages/style-runtime/package.json +++ b/packages/style-runtime/package.json @@ -41,6 +41,10 @@ }, "types": "build-types", "sideEffects": false, + "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@types/jest": "^30.0.0" + }, "publishConfig": { "access": "public" } diff --git a/packages/style-runtime/tsconfig.build.json b/packages/style-runtime/tsconfig.build.json new file mode 100644 index 00000000000000..7ff060ab6ce105 --- /dev/null +++ b/packages/style-runtime/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig.json", + "extends": "../../tsconfig.base.json" +} diff --git a/packages/style-runtime/tsconfig.json b/packages/style-runtime/tsconfig.json index 7ff060ab6ce105..24d3b6ad841b4f 100644 --- a/packages/style-runtime/tsconfig.json +++ b/packages/style-runtime/tsconfig.json @@ -1,4 +1,11 @@ { "$schema": "https://json.schemastore.org/tsconfig.json", - "extends": "../../tsconfig.base.json" + "extends": "../../tsconfig.dev.base.json", + // Tests live beside src, not under it. + "compilerOptions": { + "rootDir": "." + }, + "files": [ "global.d.ts" ], + "include": [ "test/**/*.ts" ], + "references": [ { "path": "./tsconfig.build.json" } ] } diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 309d80243d1f67..eedba9749097d5 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -13,7 +13,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514)) +- Point tsconfig references at split dependencies' build projects. ([#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Collapse the `tsconfig.src.json`/`tsconfig.bin.json`/`tsconfig.test.json` projects into the repository-standard split of `tsconfig.build.json` and a default dev `tsconfig.json`. ([#81509](https://github.com/WordPress/gutenberg/pull/81509)) - Update Terrazzo packages to 2.5.0, use its resolver for mode overrides, and restore token linting with semantic WCAG AA contrast checks ([#81082](https://github.com/WordPress/gutenberg/pull/81082)). diff --git a/packages/theme/tsconfig.build.json b/packages/theme/tsconfig.build.json index 4204e29a55127b..b70e89d7e4c253 100644 --- a/packages/theme/tsconfig.build.json +++ b/packages/theme/tsconfig.build.json @@ -9,6 +9,6 @@ { "path": "../deprecated/tsconfig.build.json" }, { "path": "../element/tsconfig.build.json" }, { "path": "../private-apis" }, - { "path": "../style-runtime" } + { "path": "../style-runtime/tsconfig.build.json" } ] } diff --git a/packages/theme/tsconfig.json b/packages/theme/tsconfig.json index 20f997c8dc4235..286598bf88d383 100644 --- a/packages/theme/tsconfig.json +++ b/packages/theme/tsconfig.json @@ -24,6 +24,6 @@ { "path": "./tsconfig.build.json" }, { "path": "./tsconfig.plugins.json" }, { "path": "../compose/tsconfig.build.json" }, - { "path": "../style-runtime" } + { "path": "../style-runtime/tsconfig.build.json" } ] } diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 5a32f4f4e57234..4a6dfdfba02f8c 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -21,7 +21,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81509](https://github.com/WordPress/gutenberg/pull/81509), [#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81516](https://github.com/WordPress/gutenberg/pull/81516)) +- Point tsconfig references at split dependencies' build projects. ([#81509](https://github.com/WordPress/gutenberg/pull/81509), [#81514](https://github.com/WordPress/gutenberg/pull/81514), [#81516](https://github.com/WordPress/gutenberg/pull/81516), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81515](https://github.com/WordPress/gutenberg/pull/81515)) ## 0.20.0 (2026-08-12) diff --git a/packages/ui/tsconfig.build.json b/packages/ui/tsconfig.build.json index f9f830b8610024..ded16354992de4 100644 --- a/packages/ui/tsconfig.build.json +++ b/packages/ui/tsconfig.build.json @@ -17,7 +17,7 @@ { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../theme/tsconfig.build.json" } ] } diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 2f37ce9403d940..1c24d47a4b69a1 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -28,7 +28,7 @@ { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../theme/tsconfig.build.json" } ] } diff --git a/packages/ui/tsconfig.stories.json b/packages/ui/tsconfig.stories.json index f3b3325d99a25c..4b4a9b3e6c9a11 100644 --- a/packages/ui/tsconfig.stories.json +++ b/packages/ui/tsconfig.stories.json @@ -30,7 +30,7 @@ { "path": "../keycodes/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../theme/tsconfig.build.json" } ] } diff --git a/packages/undo-manager/tsconfig.json b/packages/undo-manager/tsconfig.json index a3c336bec45609..aaf003a7bd2dc5 100644 --- a/packages/undo-manager/tsconfig.json +++ b/packages/undo-manager/tsconfig.json @@ -4,5 +4,5 @@ "compilerOptions": { "types": [ "node" ] }, - "references": [ { "path": "../is-shallow-equal" } ] + "references": [ { "path": "../is-shallow-equal/tsconfig.build.json" } ] } diff --git a/packages/widget-dashboard/tsconfig.build.json b/packages/widget-dashboard/tsconfig.build.json index e426a069679053..0c1752cc0e9715 100644 --- a/packages/widget-dashboard/tsconfig.build.json +++ b/packages/widget-dashboard/tsconfig.build.json @@ -16,7 +16,7 @@ { "path": "../icons/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" }, { "path": "../viewport" }, { "path": "../widget-primitives/tsconfig.build.json" } diff --git a/packages/widget-dashboard/tsconfig.json b/packages/widget-dashboard/tsconfig.json index 375e6212796ccd..f00a7c2fb0217d 100644 --- a/packages/widget-dashboard/tsconfig.json +++ b/packages/widget-dashboard/tsconfig.json @@ -17,7 +17,7 @@ { "path": "../icons/tsconfig.build.json" }, { "path": "../primitives" }, { "path": "../private-apis" }, - { "path": "../style-runtime" }, + { "path": "../style-runtime/tsconfig.build.json" }, { "path": "../ui/tsconfig.build.json" }, { "path": "../viewport" }, { "path": "../widget-primitives/tsconfig.build.json" } diff --git a/packages/wp-build/tsconfig.json b/packages/wp-build/tsconfig.json index 606e028c8e593a..15920070b6e66f 100644 --- a/packages/wp-build/tsconfig.json +++ b/packages/wp-build/tsconfig.json @@ -17,7 +17,7 @@ "noEmit": true, "outDir": ".cache" }, - "references": [ { "path": "../style-runtime" } ], + "references": [ { "path": "../style-runtime/tsconfig.build.json" } ], "include": [ "." ], "exclude": [ // Excluded to maintain consistency with bin/tsconfig.json diff --git a/tools/validation/validate-tsconfig.mjs b/tools/validation/validate-tsconfig.mjs index ca91e4526a624d..ca92f5245303d5 100755 --- a/tools/validation/validate-tsconfig.mjs +++ b/tools/validation/validate-tsconfig.mjs @@ -167,10 +167,36 @@ function srcProjectReferences( srcProject, packageName ) { return collected; } +/** + * Whether the package has TypeScript test or story files anywhere, which + * only a dev project checks. The single build project never sees them. + * + * @param {string} packageName Package directory name. + * @return {boolean} Whether dev files exist. + */ +function hasDevFiles( packageName ) { + return ( + glob.sync( '**/{test,tests,__tests__,stories}/**/*.{ts,tsx}', { + cwd: resolve( repoRoot, 'packages', packageName ), + ignore: [ 'node_modules/**', 'build/**', 'build-*/**' ], + } ).length > 0 || + glob.sync( '**/*.story.{ts,tsx}', { + cwd: resolve( repoRoot, 'packages', packageName ), + ignore: [ 'node_modules/**', 'build/**', 'build-*/**' ], + } ).length > 0 + ); +} + for ( const packageName of packagesWithTypes ) { const { srcProject, devProject, storiesProject } = packageProjects( packageName ); + if ( ! devProject && hasDevFiles( packageName ) ) { + reportError( + `Missing dev project for the TypeScript test or story files of packages/${ packageName }` + ); + } + if ( srcProject && ! buildSolutionReferences.has( srcProject ) ) { reportError( `Missing reference to "${ relative( diff --git a/tools/validation/validate-tsconfig.test.js b/tools/validation/validate-tsconfig.test.js index e7e4327feb7380..a46614c893a96b 100644 --- a/tools/validation/validate-tsconfig.test.js +++ b/tools/validation/validate-tsconfig.test.js @@ -549,3 +549,20 @@ test( 'passes when a build project keeps every dev-file pattern of the base', () expect( result.status ).toBe( 0 ); } ); + +test( 'fails when a package with TypeScript test files has no dev project', () => { + const repoRoot = createRepo( { + packages: { blob: { tsconfigs: { 'tsconfig.json': [] } } }, + build: [ 'packages/blob' ], + root: [ './tsconfig.build.json' ], + } ); + mkdirSync( join( repoRoot, 'packages/blob/test' ), { recursive: true } ); + writeFileSync( join( repoRoot, 'packages/blob/test/index.ts' ), '' ); + + const result = runValidator( repoRoot ); + + expect( result.status ).not.toBe( 0 ); + expect( result.stderr ).toContain( + 'Missing dev project for the TypeScript test or story files of packages/blob' + ); +} ); diff --git a/tsconfig.build.json b/tsconfig.build.json index dbb035c02f6b59..c45e663942e569 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -46,7 +46,7 @@ { "path": "packages/interactivity/tsconfig.build.json" }, { "path": "packages/interactivity-router/tsconfig.main.json" }, { "path": "packages/interactivity-router/tsconfig.full-page.json" }, - { "path": "packages/is-shallow-equal" }, + { "path": "packages/is-shallow-equal/tsconfig.build.json" }, { "path": "packages/kebab-case" }, { "path": "packages/keycodes/tsconfig.build.json" }, { "path": "packages/keyboard-shortcuts" }, @@ -74,7 +74,7 @@ { "path": "packages/server-side-render/tsconfig.build.json" }, { "path": "packages/shortcode/tsconfig.build.json" }, { "path": "packages/style-engine" }, - { "path": "packages/style-runtime" }, + { "path": "packages/style-runtime/tsconfig.build.json" }, { "path": "packages/sync/tsconfig.build.json" }, { "path": "packages/theme/tsconfig.build.json" }, { "path": "packages/theme/tsconfig.plugins.json" }, diff --git a/tsconfig.json b/tsconfig.json index d71aa6da98a155..de4dbedf19f19b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,6 +32,7 @@ { "path": "packages/image-cropper" }, { "path": "packages/interactivity" }, { "path": "packages/interactivity-router" }, + { "path": "packages/is-shallow-equal" }, { "path": "packages/jest-console" }, { "path": "packages/keycodes" }, { "path": "packages/media-editor" }, @@ -43,6 +44,7 @@ { "path": "packages/report-flaky-tests" }, { "path": "packages/server-side-render" }, { "path": "packages/shortcode" }, + { "path": "packages/style-runtime" }, { "path": "packages/sync" }, { "path": "packages/theme" }, { "path": "packages/token-list" }, From 49690a424fff6fe532f741b2d372f7f17aec6e73 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 17 Aug 2026 02:01:04 -0700 Subject: [PATCH 4/7] TypeScript: Keep the clean-up hint when the type check fails, add script aliases npm run typecheck now goes through build-scripts and prints the same hint the build did, so a red CI run still points at the fix. The declaration check gets a root alias for CI and local use. --- .github/workflows/static-checks.yml | 2 +- package.json | 3 ++- tools/build-scripts/package.json | 3 ++- tools/build-scripts/typecheck.mjs | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tools/build-scripts/typecheck.mjs diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 6847a36aec39df..c4973a2e5020b3 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -120,7 +120,7 @@ jobs: - name: Check type declaration files # Runs against the declarations the type check just emitted; # the bundle build below skips types and with them this check. - run: npm run --workspace @wordpress/build-scripts check-type-declarations + run: npm run check:type-declarations - name: Build packages run: npm run build -- --skip-types diff --git a/package.json b/package.json index ede0a8e1086032..a8b9b210d4a529 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "agents:setup": "npm run --workspace @wordpress/agent-tools setup --", "build": "npm run --workspace @wordpress/build-scripts build:all --", "build:plugin-zip": "bash ./bin/build-plugin-zip.sh", + "check:type-declarations": "npm run --workspace @wordpress/build-scripts check-type-declarations --", "clean:package-types": "npm run --workspace @wordpress/build-scripts clean:package-types --", "clean:packages": "npm run --workspace @wordpress/build-scripts clean:packages --", "dev": "npm run --workspace @wordpress/build-scripts dev --", @@ -185,7 +186,7 @@ "test:unit:update": "npm run --workspace @wordpress/unit-tests test:unit -- --updateSnapshot", "test:unit:watch": "npm run --workspace @wordpress/unit-tests test:unit:watch --", "pretypecheck": "npm run --workspace @wordpress/build-scripts generate-worker-placeholders --", - "typecheck": "tsc --build", + "typecheck": "npm run --workspace @wordpress/build-scripts typecheck --", "wp-env": "wp-env", "wp-env-test": "wp-env --config .wp-env.test.json" }, diff --git a/tools/build-scripts/package.json b/tools/build-scripts/package.json index 215d6832ff562f..48bd9307b40070 100644 --- a/tools/build-scripts/package.json +++ b/tools/build-scripts/package.json @@ -50,6 +50,7 @@ "build-vendors": "node ./packages/build-vendors.mjs", "generate-worker-placeholders": "node ./packages/generate-worker-placeholders.mjs", "resolve-trace-source-maps": "node ./packages/resolve-trace-source-maps.cjs", - "check-type-declarations": "node ./packages/check-build-type-declaration-files.cjs" + "check-type-declarations": "node ./packages/check-build-type-declaration-files.cjs", + "typecheck": "node ./typecheck.mjs" } } diff --git a/tools/build-scripts/typecheck.mjs b/tools/build-scripts/typecheck.mjs new file mode 100644 index 00000000000000..022920e8aa5790 --- /dev/null +++ b/tools/build-scripts/typecheck.mjs @@ -0,0 +1,20 @@ +#!/usr/bin/env node +import path from 'path'; +import { fileURLToPath } from 'url'; +import spawn from 'cross-spawn'; + +const __dirname = path.dirname( fileURLToPath( import.meta.url ) ); +const ROOT_DIR = path.resolve( __dirname, '../..' ); + +/* Same failure hint as the build, so a red CI run points at the fix. */ +const result = spawn.sync( 'tsc', [ '--build', ...process.argv.slice( 2 ) ], { + cwd: ROOT_DIR, + stdio: 'inherit', +} ); + +if ( result.status !== 0 ) { + console.error( + '\n❌ Type check failed. Try cleaning up first: `npm run clean:package-types`' + ); +} +process.exit( result.status ?? 1 ); From dd2884243480b620080261ddfc07ab97d425ca3d Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 17 Aug 2026 02:01:06 -0700 Subject: [PATCH 5/7] Build: Drop the migration wording from the declaration check comment --- .../packages/check-build-type-declaration-files.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/build-scripts/packages/check-build-type-declaration-files.cjs b/tools/build-scripts/packages/check-build-type-declaration-files.cjs index d38096133929a4..f9ffb2399fcd97 100644 --- a/tools/build-scripts/packages/check-build-type-declaration-files.cjs +++ b/tools/build-scripts/packages/check-build-type-declaration-files.cjs @@ -29,8 +29,8 @@ const chalk = require( 'chalk' ); */ async function packageNeedsExtraCheck( packagePath ) { /* - * Migrated packages compile src from tsconfig.build.json; the default - * tsconfig.json is their dev project. + * A split package compiles src from tsconfig.build.json; its default + * tsconfig.json is the dev project. */ let configPath = path.join( packagePath, 'tsconfig.build.json' ); try { From 3142bd6f10c42ce750fdf9e78f77b551699bf1bc Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 17 Aug 2026 02:01:08 -0700 Subject: [PATCH 6/7] Docs: Say precisely which project a package registers and what the type check covers --- AGENTS.md | 2 +- packages/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7a669bd8c7c1ff..c7a0ccd8eddf48 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,7 @@ Read only what your task needs, when it needs it: ```bash npm run format # Fix JS formatting npm run lint:js # Check JS linting -npm run typecheck # Type check everything, including tests and stories +npm run typecheck # Type check sources, plus TypeScript tests and stories vendor/bin/phpcbf # Fix PHP standards vendor/bin/phpcs # Check PHP standards diff --git a/packages/README.md b/packages/README.md index b8df58bd876ae5..7dc22ae5b26d26 100644 --- a/packages/README.md +++ b/packages/README.md @@ -327,7 +327,7 @@ Gutenberg uses TypeScript for several reasons, including: Gutenberg uses TypeScript by running the TypeScript compiler (`tsc`) on select packages. These packages benefit from type checking and produced type declarations in the published packages. -A package opts in to TypeScript tooling with a `tsconfig.json` build project registered in the root `tsconfig.build.json` references. Packages with test or story files split into two projects: +A package opts in to TypeScript tooling with a build project registered in the root `tsconfig.build.json` references: `tsconfig.json` for a package without TypeScript dev files, `tsconfig.build.json` for one that splits. Packages with TypeScript test or story files split into two projects: - `tsconfig.build.json` is the build project: it covers `src`, emits declarations to `build-types`, and is what other packages and `npm run build` consume. - `tsconfig.json` is the dev project: it covers test and story files with `noEmit`, so `npm run typecheck` and the IDE can check them without their declarations ending up in the published package. From 689110215a4ccb91f1778fabc244e015e7ddb2b3 Mon Sep 17 00:00:00 2001 From: Manzoor Wani Date: Mon, 17 Aug 2026 19:34:02 -0700 Subject: [PATCH 7/7] Packages: Link the finalize PR from the repointed changelog entries --- packages/admin-ui/CHANGELOG.md | 2 +- packages/widget-dashboard/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/admin-ui/CHANGELOG.md b/packages/admin-ui/CHANGELOG.md index ebd87f5bbecc92..1adabfec1782f0 100644 --- a/packages/admin-ui/CHANGELOG.md +++ b/packages/admin-ui/CHANGELOG.md @@ -12,7 +12,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81515](https://github.com/WordPress/gutenberg/pull/81515)) +- Point tsconfig references at split dependencies' build projects. ([#81515](https://github.com/WordPress/gutenberg/pull/81515), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81514](https://github.com/WordPress/gutenberg/pull/81514)) ## 2.8.0 (2026-08-12) diff --git a/packages/widget-dashboard/CHANGELOG.md b/packages/widget-dashboard/CHANGELOG.md index 55bd7179cec8ce..9a1fafdd9e16c7 100644 --- a/packages/widget-dashboard/CHANGELOG.md +++ b/packages/widget-dashboard/CHANGELOG.md @@ -13,7 +13,7 @@ ### Internal -- Point tsconfig references at split dependencies' build projects. ([#81509](https://github.com/WordPress/gutenberg/pull/81509), [#81515](https://github.com/WordPress/gutenberg/pull/81515), [#81516](https://github.com/WordPress/gutenberg/pull/81516)) +- Point tsconfig references at split dependencies' build projects. ([#81509](https://github.com/WordPress/gutenberg/pull/81509), [#81515](https://github.com/WordPress/gutenberg/pull/81515), [#81516](https://github.com/WordPress/gutenberg/pull/81516), [#81518](https://github.com/WordPress/gutenberg/pull/81518)) - Split tsconfig into a build project and a default dev project so dev files are type checked without publishing their declarations. ([#81514](https://github.com/WordPress/gutenberg/pull/81514)) ## 0.5.0 (2026-08-12)