Babel 与 TypeScript (编译与类型检查)
1. 面试题
Q: 如果项目中用 Babel 处理 TypeScript,那类型检查是谁做的?Babel 的 @babel/preset-typescript 和 ts-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。
- 流程:
- Babel: 负责 只做移除类型注解 (Strip Types),不做类型检查。不管有没有类型错误,直接生成 JS。速度极快。
- 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.