fix(metadata-core): 让 test/ 层真的进 tsc,@ts-expect-error 不再是幽灵检查 (#5476) - #5592
Merged
Conversation
`packages/metadata-core/tsconfig.json` 的 `include` 是 `["src/**/*"]`,而六个测试 文件住在 sibling 的 `test/` 树里——没有任何 `exclude` 指向它们,它们只是落在 include 根之外。于是 `typecheck`(裸 `tsc --noEmit`,读的就是这份 config)从没读过它们, `TESTS_COVERED` 也看不见(只统计 include 根之下,本包 testFiles 计数为 0)。 `test/types.test.ts:51` 那条 `@ts-expect-error` 因此从不被求值。 反向验证走的是常规方向:在新 program 下删掉该指令行,`test/types.test.ts(51,7)` 报 TS2353 —— `version` 不在 `Pick< MetaRef, 'org' | 'type' | 'name' >` 里;而在 origin/main 的旧 program(裸 `tsc --noEmit`)下删掉同一行,退出码仍是 0。指令钉的是 真事实,缺的只是编译它的程序,所以保留指令、补程序。 - `packages/metadata-core/tsconfig.test.json`:build config 的 sibling, `package.json` 的 `typecheck` 指名它(`tsc --noEmit -p tsconfig.test.json`)。 只改 `rootDir`(`src` → 包根)和 `noEmit`:继承的 `rootDir: src` 会对全部六个 `test/**` 报 TS6059,那是检查本身配错,不是测试写错;而在 BUILD config 里放宽 `rootDir` 不行 —— 那份 config 是要 emit 的(`dev: tsc --watch`、`outDir: dist`), 包根 rootDir 会把 `dist/index.js` 挪成 `dist/src/index.js` 并开始写 `dist/test/**/*.test.js`,后者正是 ci.yml 拦的东西。 - 与 spec/client 两先例不同,module 语义**不动**:本包有 `"type": "module"`, NodeNext 已按 ESM 读这些文件,且比 `bundler` 更严(保住必须发布的 `.js` 导入 后缀)。strictness 一律继承,不放松。 - 无 `test-typecheck-debt.json`:整个 test 层在新 config 下 0 error,逐文件 EXACT 棘轮(spec 691、client 6 才需要)在这里什么也不装,却要多一个 `tsx` 依赖。零残 余时裸 `tsc -p` 是更强的门:任何错误立即红,没有台账可加。 - 同 PR 删除 `scripts/check-type-check-coverage.mjs` 的 `PHANTOM_PIN_DEBT` 条目, RECONCILED 本来也会强制删。台账就此清空——把 `typecheck` 改回裸 `tsc --noEmit` 验证过:PINS_CHECKED 立刻红,这条门是承重的。 Fixes #5476 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V7WetGmnfoXNn8cLieKKmx
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
August 5, 2026 20:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5476
前提复核(origin/main @
e900015)前提成立,两条事实都在:
packages/metadata-core/tsconfig.json仍是include: ["src/**/*"],六个测试文件住在 sibling 的test/树里。没有任何exclude指向它们——它们只是落在 include 根之外,这正是本单与@ts-expect-error退役 pin 在packages/spec里是幽灵检查:tsconfig 把**/*.test.ts排除出唯一的tsc --noEmit#5286(spec 被**/*.test.ts显式排除)成因不同的地方;scripts/check-type-check-coverage.mjs的PHANTOM_PIN_DEBT里'packages/metadata-core/test/types.test.ts'条目仍在。后果也如实复现:
typecheck是裸tsc --noEmit,读的就是那份 config,所以test/整棵树从没被任何类型检查器读过;TESTS_COVERED只统计 include 根之下,本包testFiles计数为 0,既不报警也不进TEST_DEBT。反向验证:常规方向(before green / after red),已跑
指令在
test/types.test.ts:51,钉的是refKey的入参形状。新 program 下删掉那一行 → 红:
origin/main 的旧 program(裸
tsc --noEmit)下删掉同一行 → 退出码 0,全绿。也就是说:指令钉的是真事实(
refKey收的是Pick< MetaRef, 'org' | 'type' | 'name' >,version是多余属性),缺的只是编译它的程序。所以修法是保留指令、补上程序,而不是像 #5449 / PR #5546 那样删指令(那一例编译后报 TS2578 unused,方向是镜像的)。路线选择:路线 2(sibling config),因为路线 1 在本包会撞 emit 约束
先量后定。直接把
include扩成["src/**/*", "test/**/*"](issue 的路线 1)实测报 TS6059 x6:本包
tsconfig.json带rootDir: "src"+outDir: "dist",而这份 config 是要 emit 的(dev: "tsc --watch")。把rootDir放宽到包根会把dist/index.js挪成dist/src/index.js(打断main/exports),并开始写dist/test/**/*.test.js——后者正是 ci.yml「No compiled test files in any dist」拦的东西。emit 约束属于 build config,所以路线 1 只能连rootDir一起改,代价不可接受。于是照两先例的既定形状走路线 2。
改动
packages/metadata-core/tsconfig.test.json(新增)build config 的 sibling,
package.json的typecheck指名它。相对 build config 只改两项,其余全部继承:rootDir由src放宽到包根 —— 只影响 emit 布局,而这个 program 不 emit(noEmit: true);继承src时那六个 TS6059 是检查配错,不是测试写错;noEmit: true。module 语义刻意不动,这是与 spec / client 两先例的唯一实质差异:那两个包没有
"type": "module",build config 的 NodeNext 把 ESM 测试当 CJS 编,报出来的是关于「检查」的错(TS2835 / TS1470 / TS2550),换esnext/bundler是对齐 vitest 的保真。@objectstack/metadata-core是"type": "module",NodeNext 本就按 ESM 读这些文件,而且比bundler更严——它守住本包必须发布的.js导入后缀(bundler下漏后缀能编过、Node ESM 运行时才炸)。没有要修的,就不改。strictness 一律继承,不放松。没有
test-typecheck-debt.json,这是刻意的整个 test 层在新 config 下 0 error。逐文件 EXACT 收缩台账(
scripts/check-test-typecheck.mts,spec 691 / client 6 才需要)在这里什么也装不下,却要给本包多加一个tsx依赖和两个脚本。零残余时裸tsc --noEmit -p tsconfig.test.json是更强的门:任何错误立即红,没有台账可加。将来真攒下改不动的残余,那时再接共享脚本。check-type-check-coverage.mjs自己的 self-test fixture 就把tsc --noEmit && tsc --noEmit -p tsconfig.test.json列为合法形状。(为佐证不是偷懒:共享脚本对本包也跑得通,输出
0 file(s) / 0 error(s) held in test-typecheck-debt.json——它确实只是空转。)scripts/check-type-check-coverage.mjs仅删
PHANTOM_PIN_DEBT对应条目(RECONCILED 本来也会强制删),台账就此清空,并留一句说明「空是终态、下一例的入口是 PINS_CHECKED 变红而不是新增条目」。另有一处注释时态修正:testCoverage的文档说「packages/metadata-core/test/is outside include」——本 PR 之后这句变成假的,改为过去时并标注 #5476。验证(全部前台跑完,真实输出)
门是承重的,不是装饰:把
typecheck改回裸tsc --noEmit(即台账已删、配置没被指名)后重跑 gate:无 changeset
照两先例的取舍:PR #5478 与 PR #5546 都没有 changeset。本 PR 只动 build / test 配置与仓库门,发布产物(
dist)逐字节不变,对使用者不可见。关联:#5286(不变式与台账来源)、#4311(typecheck 覆盖棘轮)、#5449 / PR #5546(client,镜像方向的那一例)、PR #5478(spec,机制来源)。
Generated by Claude Code