TypeScript 从 JavaScript 迁移

存量 JavaScript 项目想获得类型检查,不必推倒重来。TypeScript 官方路线是"渐进迁移":先让编译器同时接受 JS 与 TS,再逐个文件重命名、逐步开启严格检查,风险小且能持续交付。

迁移准备

先安装 TypeScript 并生成 tsconfig.json,开启 allowJs 让编译器读取 JS 文件:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "allowJs": true,
    "checkJs": false,
    "outDir": "./dist",
    "strict": false
  },
  "include": ["src"]
}

allowJs 允许 .js 文件参与编译,checkJs 决定是否检查它们,两者都可随时调整。

让 JS 先被检查

迁移初期不必改文件名,先在个别 JS 文件顶部加 // @ts-check,让该文件享受类型检查:

// @ts-check
function greet(name) {
  return "你好," + name;
}
const msg = greet(42); // 此时会提示:number 不能赋给期望的 string 参数
console.log(msg);

把检查范围逐步扩大,等团队适应后再统一把 checkJs 打开。

逐个重命名文件

把确认无误的 .js 改成 .ts,顺序建议"叶子模块优先、依赖它的文件在后"。混合期间用临时手段过渡:

// 旧代码暂时没类型,先显式标注,避免 implicit any
const legacy = require("./legacy") as any;

// 个别第三方 API 实在没有类型时,用 expect-error 明确"此处已知报错"
// @ts-expect-error 等待升级 @types 包
legacy.weirdMethod();

重命名后立刻跑 tsc --noEmit 验证,出错的点当场修或标记,不积压。

补齐第三方类型

绝大多数流行库都能从 DefinitelyTyped 安装类型声明:

npm i -D @types/node @types/express @types/lodash

找不到官方包时,为最小可用的 API 写一个 .d.ts 声明文件即可:

// legacy.d.ts
export declare function legacyMethod(a: string): number;

逐步开启严格模式

全部文件转为 .ts 后,再按顺序收紧开关:noImplicitAny、strictNullChecks、strictFunctionTypes,最后直接 strict: true。并把 tsc --noEmit 加入 CI,让类型检查成为提交门禁。

小结

渐进迁移的要诀是"先能编译、再谈严格":allowJs 混合编译 → 逐个改名 → 补齐声明 → 逐项开启 strict。每步都可回退、可验证,存量项目就能平滑切换到 TypeScript。

笔记加载中…