Skip to content

@ts-expect-error 退役 pin 在 packages/spec 里是幽灵检查:tsconfig 把 **/*.test.ts 排除出唯一的 tsc --noEmit #5286

Description

@os-zhuang

在 #4938 的退役工作中发现,记录备查,未认领。基线 origin/main @ 3905c00。

事实

packages/spec/tsconfig.json 的 exclude 含 "**/*.test.ts",而该包的 typecheck 脚本就是裸 tsc --noEmit(读同一份 tsconfig):

packages/spec | typecheck=tsc --noEmit | exclude=["node_modules","dist","**/*.test.ts"]

所以 spec 测试文件里的任何类型层断言都不被任何 gate 求值。vitest 走 esbuild 转译、直接剥类型,不做 typecheck(vitest.config 里没有 typecheck 段);CI 里也没有第二个把 spec 测试纳入编译的步骤。

我是这样撞上的:给 #4938 的退役写了两条类型层 pin

// @ts-expect-error — `HttpServerConfig` was retired with its schema.
type _Retired = httpServer.HttpServerConfig;

pnpm --filter @objectstack/spec typecheck 通过。把指令行删掉,它还是通过 —— 两种状态都绿,说明这一行从来没被编译过。若指令真的生效,类型存在时应报 TS2578(unused @ts-expect-error),类型不存在时应报 TS2694,两边都不可能静默。据此我把那两条 pin 从 PR 里撤了,改用 api-surface.json 作为类型导出的见证。

为什么值得单独立单

树上已经有 4 个 spec 测试文件、约 14 条 @ts-expect-error,其中相当一部分正是退役 pin —— 即 spec-property-retirement playbook 明确倚重的那条 "tsc 是最好的清扫器" 通道:

packages/spec/src/data/object.test.ts:904   // @ts-expect-error — compactLayout was retired (#2536)
packages/spec/src/data/object.test.ts:946   // @ts-expect-error — the detail block was removed (ADR-0085)
packages/spec/src/data/object.test.ts:1119  // @ts-expect-error — compactLayout was retired by framework#2536
packages/spec/src/data/object.test.ts:1130  // @ts-expect-error — `detail` was removed by ADR-0085
packages/spec/src/data/hook.test.ts:837     // @ts-expect-error — `enabled` is not a hook key (#4207 guidance)
packages/spec/src/system/translation-typegen.test.ts:102,119,128
packages/spec/src/contracts/sharing-service.test.ts:30,49

这些行读起来像"如果 compactLayout 回来了,typecheck 会红",实际上不会。它们通过运行时断言恰好还有一半覆盖(safeParse 那半),但类型面完全无守卫 —— 属于 phantom check 类:看起来验证过,其实一次都没跑。

packages/runtime / packages/rest 的 tsconfig 有同样的 exclude(packages/rest 甚至没有 typecheck 脚本);packages/cli 的 exclude 为空,是对照组。范围有多大需要一次横扫,不在本单臆断。

可能的处置(供 triage,未裁决)

  • A. 给 spec 增加 tsconfig.test.json(include 含测试、noEmit),typecheck 跑两份 —— 不动 build 的 rootDir/exclude(那个 exclude 存在是有理由的:CI ci.yml:824-849 有一条"编译产物里不得出现测试文件"的 gate)。
  • B. 打开 vitest 的 typecheck 支持,让类型断言随测试一起跑。
  • C. 判定类型层 pin 不是本仓的守卫手段,把这 14 条改写成运行时断言或删除,并在 playbook 里写明"tsc 清扫器只覆盖非测试源码"。

倾向 A:代价最小,且保住 playbook 依赖的那条通道;但这决定了退役工作以后能不能继续把 tsc 当清扫器用,应由维护者裁。

关联:#4938、spec-property-retirement skill §1/§6、ADR-0049。

Activity

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions