精准统计typescript业务代码覆盖率需排除框架胶水、类型定义等非业务代码,限定src/services/、src/domain/等路径,配置collectcoveragefrom与coveragepathignorepatterns,禁用类型声明插桩,过滤空语句与常量文件,并启用分支覆盖率验证隐式逻辑。

在 TypeScript 项目中精准统计纯业务代码的覆盖率,关键不是“把所有 .ts 文件都塞进报告”,而是主动排除框架胶水、类型定义、测试辅助、构建产物等非业务逻辑,让覆盖率数字真实反映核心逻辑的验证程度。
明确业务代码范围,用路径和命名约定隔离
先定义什么是“纯业务代码”:通常是 src/ 下与领域逻辑强相关的部分,比如 src/services/、src/domain/、src/lib/(不含工具函数)、src/features/**/logic.ts 等。避免笼统写 src/**/*。
- 在 Jest 配置中用
collectCoverageFrom精确声明源码路径:collectCoverageFrom: ["src/services/**/*.{ts,tsx}", "src/domain/**/*.{ts,tsx}"] - 配合
coveragePathIgnorePatterns排除干扰:["node_modules/", "types/", "__tests__/", "mocks/", "test-utils/", ".*\.d\.ts$"] - Vitest 用户可在
coverage.include中同样限定目录,同时设置exclude过滤类型文件和测试相关路径
屏蔽类型层干扰,禁用类型检查对覆盖率的影响
TypeScript 编译阶段不生成 JS 的语句(如 type、interface、declare)本就不参与运行,但某些插桩工具若未正确识别,可能误将 import type 或 export type 当作可执行语句计数——导致分母虚高、覆盖率被拉低。
- 确保使用
ts-jest(v29+)或vitest(v1.6+),它们默认跳过类型声明插桩 - 检查 Babel 插件配置(如
babel-plugin-istanbul),确认include不含**/*.d.ts,且exclude明确包含类型文件模式 - 若用
nyc,加--exclude-after-remap "**/*.d.ts"防止 sourcemap 回溯引入类型文件
剔除运行时无关代码,聚焦可执行逻辑
即使在业务目录下,也存在不参与实际业务流转的代码:空 catch 块、兜底 console.warn、未导出的私有常量、条件编译残留等。这些会稀释覆盖率指标。
- 用 Istanbul 的
ignoreClassMethods(Jest)或自定义reporter过滤掉明显无逻辑的语句(如仅含return;或throw new Error();的函数体) - 在
lcov合并后做二次过滤:lcov --remove coverage/lcov.total.info '**/constants.ts' '**/*.config.ts' '*/mock*.ts' --output-file coverage/lcov.business.info - 启用 ESLint 规则
no-empty、no-console(warn 级别以上)提前拦截低价值语句,减少覆盖“假目标”
验证是否真覆盖了业务意图,不止于行数
业务代码常含隐式分支(如解构失败、Promise reject、optional chaining 短路)。单看行覆盖率易误判——某行“绿了”,不代表其所有执行路径都被测到。
- 强制开启分支覆盖率:
branches: 85并写入coverageThreshold,尤其关注src/domain/下的判断逻辑 - 对关键 service 方法,手动检查 HTML 报告中标红的
if (x?.y?.z)、arr?.[0]?.id等链式访问点——它们往往代表未覆盖的空值场景 - 结合运行时数据:用 Playwright +
coverage或 Chrome Coverage 面板,在真实用户流中验证业务入口是否触发了预期的 service 调用链











