ci(scripts): 用独立 tsconfig.scripts.json 给 scripts/ 补上类型门 (#3494) - #3498
Merged
Conversation
…on (#3494) `scripts/` is not a workspace package, so `pnpm type-check` (turbo, which walks package.json `scripts`) structurally cannot reach it, and check-type-check-coverage.mjs decides coverage per PACKAGE so it could not see the gap either. Every file in `scripts/__tests__/` was therefore compiled by nothing at all - ten pin tests holding ci.yml, docs-links.yml, lint.yml, the changeset guard, the control-byte scanner and the shadcn local patches in place. A pin test the compiler never reads can assert a contract that no longer type-checks and still print green. Measured here: a provably-false type-level assertion appended to ci-cd-pipeline-doc.test.ts left `vitest run` at 13 passed, because type assertions are erased at runtime. - tsconfig.scripts.json: standalone (NOT extending tsconfig.base.json, whose `exclude` lists the test globs and would have made the project vacuous), strict, noEmit, covering `scripts/**/*.ts` by glob. - allowJs:true / checkJs:false, chosen by measurement rather than assumption: allowJs:false left 8 errors needing hand-written .d.mts files (a second source of truth, free to drift); allowJs:true left 5, each a now-false `@ts-expect-error` comment, and gives the pin tests types inferred from the helper itself. Comments updated accordingly. - ci.yml `type-check` job runs `pnpm type-check:scripts` after the install; it needs no workspace build, so it stays in the cheap, fail-fast half. - scripts/__tests__/scripts-type-check.test.ts pins the coverage (every .ts on disk under scripts/ resolves into the program), that the config parses at all, and that CI actually runs it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
yinlianghui
pushed a commit
that referenced
this pull request
Aug 6, 2026
…ype gate objectui#3494 (PR #3498) adds `tsconfig.scripts.json` with `allowJs: true`, whose `include` glob covers this branch's new test file too. Neither PR can see the other, and the two land green individually while the merge is red — no git conflict, so nothing warns. Two separate problems, both found by running #3498's compilerOptions against this branch: - the `@ts-expect-error` above the `../shadcn-sync.js` import becomes TS2578 once the import has an inferred type. Removed (the sibling test files get the same treatment inside #3498). - `fetchRegistry`'s `get` option was the one destructured option without a default, so it is absent from the function's inferred signature and passing it from a `.ts` caller is TS2353. Fixed at the producer by giving it its real default (`https.get`), which also drops the `get ? { get } : undefined` dance at the call site — not by suppressing it at the consumer. Behaviour is unchanged: production still resolves `https.get`, the tests still inject `http.get`. Verified against a local copy of #3498's config — zero errors in either file; the only remaining diagnostics are the five stale directives that #3498 itself removes. Refs objectstack-ai/objectstack#5803 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
yinlianghui
marked this pull request as ready for review
August 6, 2026 13:51
This was referenced Aug 7, 2026
Open
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 #3494
前提核验(先于实现)
用
--listFilesOnly扫遍仓库 76 个 tsconfig,确认scripts/__tests__/**不在任何一个 program 里。但 issue 的表述需要收窄一格 —— 「scripts/ 在零 tsconfig 覆盖内」并不完全成立:
scripts/vite-crypto-stub.tsapps/console/tsconfig.node.json(#3305 接进了 console 的type-check)scripts/vite-maplibre-worker.tsscripts/__tests__/*.ts(10 个门禁 pin 测试)也就是说:两个非测试源文件其实有门,10 个 pin 测试一个都没有。issue 的实质结论(门禁 pin 测试自身无类型门)成立,落点不变;这里如实记下差异,避免下一个人按「整个 scripts/ 都没编译」去推断。
错误数:实测 8 条,不是 3 条
#3384 当时测得 3 条。此后
check-control-bytes.test.ts/docs-links-workflow.test.ts/shadcn-local-patches.test.ts等陆续落地,现况:顺带查清了那两条 TS2578 的成因:多行
import { … } from '…mjs'里,TS 把「缺声明」报在说明符所在行(13 / 11 行),而@ts-expect-error挂在import {上一行 —— 这两个指令从来就没生效过,只是没人编译过所以没人知道。allowJs 的取舍:两个方向都真跑了
issue 提示「allowJs/checkJs 会翻转既有
@ts-expect-error的成立性」。对同一批文件实测:allowJs: false.mjs手写.d.mts。第二份事实来源,可以无声漂移 —— 正是check-spec-symbol-derivation.mjs存在的理由。而且any会外溢:3 条 TS2345 并非真缺陷,只是any的连带allowJs: truepatchedComponents()真的是string[],3 条 TS2345 自动消失选
allowJs: true+checkJs: false。后者是刻意的边界:本项目消费 helper 的推断类型,不接管 8 个纯 JS 门禁脚本内部的类型整洁 —— 那是另一件大得多的事。副作用是这条现在更强了:改动门禁 helper 的导出签名,它的 pin 测试会红。
落点
tsconfig.scripts.json(新增) —— 独立,刻意不extendstsconfig.base.json:那是包构建配置,其exclude列了 test glob,继承过来会一个测试文件都编不到,空转通过,正是check-type-check-coverage.mjs5b 段在上一层要抓的形态。vite-*.ts:排除清单是第二件要维护的事,而且 console 哪天不再 import 就会无声掉出所有 program。重叠的代价用对齐 console 那份的选项集付掉(strict / ESNext / bundler,以及不开noImplicitReturns),这样共享文件不会一个项目绿另一个红。//而非/* */:glob 里的双星紧跟斜杠会提前闭合块注释,而解析失败的 tsconfig 不会响亮报错 —— 它退回默认值,tsc -p转头去编译整个仓库。这不是假设,是写这个文件时真踩到的,已由 pin 测试钉住。.github/workflows/ci.yml——type-checkjob 加一步pnpm type-check:scripts,放在 install 之后、Turbo 之前:program 里没有任何@object-ui/*import,不需要^build,便宜且快速失败。package.json—— 加type-check:scripts根脚本。pnpm type-check是turbo run type-check,结构上够不到无 package.json 的目录;没有这个命名脚本,这道门就只能在 CI 上跑,而本地复现不了的门,人会学会忽略它。(与type-check:coverage/check:spec-symbols/check:control-bytes同一惯例。)scripts/__tests__/scripts-type-check.test.ts(新增) —— 断言的是行为不是拼写:配置能否解析、磁盘上每个scripts/**/*.ts是否真落进 program、CI 是否真跑、是否排在 install 之后,以及「不需要 workspace 构建」这个放置前提。content/docs/guide/ci-cd-pipeline.md—— job 表里type-check行逐项列出了它跑什么。不更新就会复刻 ci-cd-pipeline.md 的 ci.yml job 表格漂移:写「Seven jobs」并列了一个不存在的 dev-server job(实际 6 个) #3451 那种「页面少报一道门」的漂移,而钉住这张表的 pin 测试恰好就在本 PR 新覆盖的目录里。验证(方向先声明,再执行)
1. 主方向 —— 预测:改前 RED、改后 GREEN。
2. 反向核验 A —— 把删掉的某个
@ts-expect-error装回去。预测 RED,且原因必须是 TS2578(证明这些指令本就已失效,不是我删掉了一道有效的抑制):3. 反向核验 B(#3181 绊线) —— 往
ci-cd-pipeline-doc.test.ts追加一个必假的类型层断言(Assert< Equal< 1, 2 > >)。这里两个方向都要看,因为它们方向相反:vitest 那一侧的绿才是要点:类型断言在运行时被擦除,跑测试永远看不见它。「pin 测试全绿」+「没有任何 program 读它」= 一个可以钉住已失效契约还照样报绿的测试。
4. pin 测试自身的空转核验 —— 把 include 改窄成
scripts/vite-*.ts。预测 RED 并点名漏掉的文件(而不是空转变绿):5. 回归与门禁
#3496 新增的
scripts/__tests__/shadcn-sync-fetch-cache.test.ts带着这一行:本 PR 之后,该目录下的
.mjs/.jsimport 会由allowJs推断出真类型,于是这个指令变成 TS2578(Unused),新加的 CI 步骤会红。两个 PR 各自都绿,合并后才红 —— git 不会报冲突。后合的一方删掉那一行注释即可(与本 PR 对另外 5 处的处理一致)。#3497 只动
shadcn-check.yml,与本 PR 无交集。无 changeset
纯 CI/工具链改动,不影响任何已发布包;根
package.json是 private,新增的是根脚本而非依赖(先例 #3437)。Generated by Claude Code