起因
我接到组里的任务,需要迁移包,但是涉及的页面基本涵盖全站了,所以我怕测试测的时候会有遗漏,以及有些隐含的错误导致上线后爆炸,所以我就执行了
shell
npx tsc --noEmit --watch false
然后我就得到了如下:

🔧 一、错误标记与基线建立(优先冻结历史问题)
-
统一抑制历史错误
使用
suppress-ts-errors
工具批量添加注释,将现有错误标记为"已知问题",避免干扰新代码检查:scssnpx suppress-ts-errors --mode baseline
- 该工具会自动在错误位置插入
// @ts-expect-error
或// @ts-ignore
注释,并附带错误代码说明。 - 优势:将历史错误转化为显式忽略清单,后续新增错误会因无抑制注释而暴露。
- 该工具会自动在错误位置插入
-
按需使用高级抑制策略
- 文件级忽略 :对错误密集且暂不重构的文件,在文件顶部添加
// @ts-nocheck
。 - 目录级配置 :通过
tsconfig.json
的exclude
字段排除非核心模块的检查(慎用)。
- 文件级忽略 :对错误密集且暂不重构的文件,在文件顶部添加
🛡️ 二、重构安全保障策略
-
隔离重构范围
-
使用
// @ts-expect-error
而非@ts-ignore
:前者要求后续修复错误后必须移除注释,否则会报错,避免遗忘。 -
示例:
c// @ts-expect-error TS2345: 历史类型不匹配,待重构 const value: string = legacyFunctionReturningNumber();
-
-
增量编译与防御性编程
-
检查范围聚焦:仅检查修改的文件,降低历史错误干扰:
cssnpx tsc --noEmit --incremental --watch false
-
防御性类型保护:对不确定的第三方库或遗留代码,使用类型断言和守卫函数:
javascriptfunction isError(value: unknown): value is Error { return value instanceof Error || (!!value && typeof value === 'object' && 'message' in value); } try { ... } catch (e) { if (isError(e)) console.error(e.stack); // 安全访问属性 }
-
🔍 三、渐进修复策略
-
错误分类与优先级排序
错误类型 处理策略 优先级 安全修复(如类型断言) 立即修复 ⭐⭐⭐ 复杂重构(接口调整) 标记后纳入迭代计划 ⭐⭐ 第三方库类型缺失 补充 @types/
包或声明文件⭐ -
分阶段修复流程
cssgraph TD A[抑制所有历史错误] --> B[开启严格模式检查新代码] B --> C[按模块逐个修复历史错误] C --> D[移除已修复模块的抑制注释]
- 每修复一个模块,移除对应文件的抑制注释,确保进度可视化。
⚙️ 四、工具链与自动化支持
-
ESLint 集成
配置规则
@typescript-eslint/ban-ts-comment
,限制抑制注释滥用:json{ "rules": { "@typescript-eslint/ban-ts-comment": ["error", {"ts-expect-error": false}] } }
- 允许
@ts-expect-error
但禁止@ts-ignore
,提升代码质量。
- 允许
-
预提交钩子检查
通过
husky
+lint-staged
确保新增代码无编译错误:json"lint-staged": { "*.ts": "tsc --noEmit --incremental" }
👥 五、团队协作与知识管理
-
错误文档化
使用
suppress-ts-errors
生成错误报告,关联到任务管理系统(如Jira):cssnpx suppress-ts-errors --report > technical-debt.md
-
定期技术债务清理
将历史错误修复纳入迭代计划,每周分配固定工时处理。
💎 总结
核心思路 :
✅ 先冻结 (抑制历史错误)→ 再隔离 (确保新代码零错误)→ 渐进修复(分模块推进)。
通过此方案可以在重构过程中精准识别新引入的错误(历史错误已被标记),同时通过类型守卫和自动化工具降低风险。对于遗留错误,建议按业务影响和修复成本制定优先级,避免陷入"全量修复"的泥潭。