补坑位记录:新增文件后必须重跑完整 typecheck

- pitfalls.md 新增 2026-09-11 条目,记 lint-staged 只做 eslint 与 prettier、不做 tsc,因此 pre-commit 绿不等于类型正确
- 按体例写现象(第 113 行 TS2322、ref 元素类型不匹配)、原因(typecheck 是在新增该文件之前跑的)、处理(每新增或改名源文件后重跑完整 typecheck,门禁顺序固定为改完 → 全量 typecheck → 定向测试 → 其余门禁)
- 验证写明:修复后 exit 0、修复前 exit 2,而定向测试修复前后都是 22 passed,说明测试通过推不出类型正确;并推广到未使用 import、类型层 props 不匹配、只有 tsc 才发现的 .tsx 泛型推断失败
- 该文件原本结尾没有换行符,追加后上一行必须重写为带换行,因此 diff 记为 11 增 1 删;已逐字核对被删行原样出现在新增行中,实际无内容丢失
This commit is contained in:
2026-09-11 20:39:19 +08:00
parent 0ef1a4ec15
commit fcaf1a8e91
+11 -1
View File
@@ -5293,4 +5293,14 @@
- **原因**:栏目页的首屏适配有 fit key 门禁——`openResourceBookChild` 只在 `resourceBookSceneSize.width/height > 0` 时把 `<projectPath>\n<projectId>\n<sortMode>\n<category>` 写进 `resourceCanvasFitKeysRef`,分页画布 layout effect 也同样要求可测量尺寸。jsdom 没有布局,两者恒为 0,于是**每次 `openResourceBookChild` 都走 fit 分支**,已存的 viewport 被重拟合覆盖。真机上尺寸非零、首次进入即写 key,再进入走 `resourceCanvasViewportTargetsRef[sortMode][category]` 恢复分支,所以这不是产品回归,是 jsdom 产物。
- **处理**:旧断言里那些"点导航切到当前栏目"的调用本来就是提前返回的空操作(`openResourceBookChild``view/category/phase` 未变时直接 return),改 helper 后它们变成了真实往返。修法是**保留全部断言、只去掉这些多余往返**(排序模式切换本身就会切换 viewport),不要为了让用例变绿去改 `index.tsx` 的 fit 逻辑,也不要把往返路径当成产品缺陷去"修"。
- **推广**:任何"进入栏目后应恢复上次 viewport"的用例,在 jsdom 里必须避免经过总览往返;要覆盖往返本身,得先给 `resourceBookSceneSize` 造出非零尺寸。
- **关联**`apps/ai-game-creator-shell/src/view/project-development/index.tsx``openResourceBookChild` / `resourceCanvasFitKeysRef` / 分页画布 layout effect)、`apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts`
- **关联**`apps/ai-game-creator-shell/src/view/project-development/index.tsx``openResourceBookChild` / `resourceCanvasFitKeysRef` / 分页画布 layout effect)、`apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts`
## 2026-09-11 新增文件后必须重跑完整 typechecklint-staged 不跑 tscpre-commit 绿不等于类型正确
- **现象**:新增 `ResourceFilterPanel.tsx` 后提交成功(pre-commit 全绿、定向测试通过),但随后补跑 `npm run ai-game-creator-shell:typecheck` 报出真实类型错误:`ResourceFilterPanel.tsx(113,10): error TS2322: Type 'RefObject<HTMLElement | null>' is not assignable to type 'Ref<HTMLDivElement> | undefined'``useRef<HTMLElement | null>` 被挂到了外层 `<div>` 上)。`exit 2`
- **原因**:门禁顺序错了——typecheck 是**在新增该文件之前**跑的(当时通过),之后只跑了定向测试与 pre-commit。而 pre-commit 的 `lint-staged` 对暂存文件**只做 `eslint``prettier`,不做 `tsc`**,因此**新文件里的类型错误没有任何一道门能拦住**。lint-staged 的日志只会列出 eslint 与 prettier 两步,不会出现类型检查字样。
- **处理**:**每新增或改名一个源文件后,必须重跑一次完整 typecheck**;门禁顺序固定为「改完 → 全量 typecheck → 定向测试 → 其余门禁」。**不要**因为 pre-commit 绿或定向测试绿就认为类型没问题。
- **验证**:修复(`useRef<HTMLDivElement | null>`)后重跑 `npm run ai-game-creator-shell:typecheck``exit 0`;修复前同命令 `exit 2`。定向测试修复前后都是 `22 passed`——**说明测试通过完全推不出类型正确**。
- **推广**:同类漏检还包括未使用的 import、只在类型层违约的 props 不匹配、以及只有 `tsc` 才发现的 `.tsx` 泛型推断失败;这几类都不会让 eslint 或 vitest 变红。
- **关联**`apps/ai-game-creator-shell/src/view/project-development/ResourceFilterPanel.tsx``package.json``ai-game-creator-shell:typecheck``format:staged`lint-staged)、提交 `5f03f050a`