Babel 与 TypeScript (编译与类型检查)

1. 面试题

Q: 如果项目中用 Babel 处理 TypeScript,那类型检查是谁做的?Babel 的 @babel/preset-typescriptts-loader 有什么区别?

2. 核心解答

这是一个非常重要的架构决策点。

(1) 方案一:ts-loader (tsc)

  • 编译工具:TypeScript Compiler (tsc)。
  • 流程:TS -> Check Types -> Compile to JS -> Babel (Optional) -> JS。
  • 优点:构建过程中 自带类型检查,类型错误会直接导致构建失败。
  • 缺点极其缓慢。尤其是项目变大后,每次保存都要重新做一遍完整类型检查,开发体验极差。

(2) 方案二:Babel (@babel/preset-typescript) + tsc (Check Only)

这是目前也是 Vue/React CLI 的主流方案

  • 编译工具:Babel。
  • 流程
    1. Babel: 负责 只做移除类型注解 (Strip Types),不做类型检查。不管有没有类型错误,直接生成 JS。速度极快
    2. tsc: 开启 noEmit 选项,只负责做 类型检查 (Type Check)。通常作为一个独立的 CI 流程,或配合 fork-ts-checker-webpack-plugin 在另外一个线程跑。
  • 优点:开发环境下 构建速度飞快 (HMR),不受类型错误阻塞。
  • 缺点:需要额外配置类型检查流程。

(3) 核心区别 (Difference)

  • const enum: Babel 以前不支持 const enum (因为它是单文件编译,无法跨文件分析),但在 Babel 7.15+ 后通过 optimizeConstEnums 选项部分支持了。
  • namespace: Babel 不支持 namespace (建议改用 module).
  • export =: Babel 不支持 TS 特有的 export = 语法。

3. 面试加分项

Q: 为什么 Babel 不能做类型检查?

因为 Babel 是 单文件编译 (File-by-File Compilation) 的。它在处理 a.ts 时,根本看不到 b.tsexport 了什么类型。而类型检查必须基于整个项目 (Project-wide) 的上下文。

4. 总结

  • ts-loader: Slow, Full Check build-time.
  • Babel: Fast, Strip Types only.
  • Best Practice: Babel for Build + tsc --noEmit for Check.