From 8140f71b39deba36ee3773ba95a9ebe105afcbe2 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 15:19:46 +0000 Subject: [PATCH] fix(docs): type-check the docs app with `next typegen`, and delete the dead `types:check` `apps/docs` declared two near-identical type-check scripts: "types:check": "fumadocs-mdx && next typegen && tsc --noEmit" "typecheck": "tsc --noEmit" `types:check` -- the thorough one -- was invoked by nothing (`git grep` over `.github/`, `scripts/`, `turbo.json` and the root `package.json` returns only its own declaration). The one CI actually runs is `typecheck`, reached through `turbo run typecheck --filter='./apps/*'`. That mattered because `tsconfig.json` includes `.next/types/**/*.ts`, which only `next typegen` produces. So the program CI type-checked was set by whether some earlier, unrelated command had populated `.next` -- and on a fresh checkout it had not. Measured with `.next` deleted, the bare script exits 0 while compiling none of the generated route types. Wiring the thorough command under the name CI already runs makes the check a function of source: it generates `.next/types/**` and `next-env.d.ts` itself before tsc reads them, and short-circuits loudly if typegen fails. Typegen costs ~1s and needs no build. Measured coverage delta (empty `.next`, `tsc --listFiles`): 1225 -> 1231 files. The six are `.next/types/validator.ts` (160 lines validating 13 route entry points), `routes.d.ts`, `root-params.d.ts`, `cache-life.d.ts`, `next-env.d.ts` and, through it, `next/image-types/global.d.ts` -- so the bare run was also type-checking a Next app without Next's own ambient declarations. Ablation, to show the added coverage is real: giving `app/[lang]/docs/layout.tsx` a `params` shape the route cannot supply leaves the old script green (exit 0, 0 errors) and makes the new one fail with TS2344 at `.next/types/validator.ts`, naming the layout and the missing param. `include` is deliberately left alone. Next writes both `.next` globs itself and re-adds either one on the next `next dev` / `next build`; running `writeConfigurationDefaults` against a narrowed copy put the `dev` glob straight back and rewrote the file. The rationale is recorded in `tsconfig.json` where the next reader would try to tidy it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt --- apps/docs/package.json | 3 +-- apps/docs/tsconfig.json | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/apps/docs/package.json b/apps/docs/package.json index 4195ea4687..746a3cccf5 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -9,9 +9,8 @@ "build": "pnpm --filter @objectstack/spec gen:schema && pnpm --filter @objectstack/spec gen:docs && NODE_OPTIONS='--max-old-space-size=4096' next build", "start": "next start", "site:lint": "next lint", - "types:check": "fumadocs-mdx && next typegen && tsc --noEmit", "postinstall": "fumadocs-mdx", - "typecheck": "tsc --noEmit" + "typecheck": "fumadocs-mdx && next typegen && tsc --noEmit" }, "dependencies": { "fumadocs-core": "16.14.4", diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json index a907d7f0c3..717956db8e 100644 --- a/apps/docs/tsconfig.json +++ b/apps/docs/tsconfig.json @@ -34,6 +34,30 @@ ] } }, + // `typecheck` runs `next typegen` before tsc on purpose, and these two + // `.next` globs are why. Next writes both of them itself + // (`writeConfigurationDefaults`) and re-adds either one on the next + // `next dev` / `next build` if you delete it -- measured by running that + // routine against a narrowed copy of this file: the `dev` glob came + // straight back and the file was rewritten. This array cannot be narrowed, + // so the honesty has to come from the script instead. + // + // .next/types/** produced by the `next typegen` that the `typecheck` + // script now runs itself, so the checked program is a + // function of source rather than of whatever `.next` an + // earlier build happened to leave behind. A bare + // `tsc --noEmit` here passed over a broken route + // signature precisely because these files were absent. + // .next/dev/types/** written only by `next dev`. Next's own build-mode + // type check filters this directory OUT of the program + // (`getDevTypesPath`, lib/typescript/runTypeCheck.js) + // "to prevent stale dev types from causing errors when + // routes have been deleted since the last dev session". + // Plain tsc has no such filter, so a leftover dev + // session can only add a local false RED here, never a + // false green. Remedy: `rm -rf apps/docs/.next`. + // + // Do not reduce `typecheck` back to a bare `tsc --noEmit`. "include": [ "next-env.d.ts", "**/*.ts",