TypeScript 7.0 已发布:大型项目迁移别只看提速,这 8 个兼容性问题更关键

TypeScript 7.0 正式发布后,最吸引人的数字是:

原生编译器,全量构建通常提升 8---12 倍。

官方在 VS Code、Sentry、Playwright、Bluesky 和 tldraw 等项目上的基准结果约为 7.7---11.9 倍;同时,测试项目的构建内存使用也出现不同程度下降。TypeScript 7 使用 Go 重写编译器和语言服务,并利用原生代码、共享内存和多线程提高性能。

不过,真实项目迁移时,最容易翻车的并不是速度。

而是团队看到:

bash 复制代码
npm install -D typescript

然后直接提交锁文件,让整个项目一夜之间切换到 TypeScript 7。

如果项目使用了旧版 tsconfig、TypeScript Compiler API、Vue、Svelte、Astro、MDX、Angular 模板检查或 ESLint 类型分析,这种升级方式很容易让编辑器、CI 和构建工具出现不同结果。

更稳的方式是:

bash 复制代码
先让 TypeScript 6 与 7 并行
再对比结果
最后切换默认编译器

一、TypeScript 7 到底快在哪里?

TypeScript 7 不只是把原来的 JavaScript 编译器重新编译了一遍。

它的编译器和语言服务改为 Go 原生实现,并增加了多线程能力。解析、类型检查、代码输出和 Project References 构建,都可以在不同程度上并行执行。

官方给出的部分全量构建结果如下:

项目 TypeScript 6 TypeScript 7 加速
VS Code 125.7 秒 10.6 秒 11.9 倍
Sentry 139.8 秒 15.7 秒 8.9 倍
Bluesky 24.3 秒 2.8 秒 8.7 倍
Playwright 12.8 秒 1.47 秒 8.7 倍
tldraw 11.2 秒 1.46 秒 7.7 倍

但这些数据不能直接套到自己的项目。

项目规模、CPU 核心数、内存、Project References、声明文件生成和磁盘性能都会影响结果。

所以升级后的第一件事不是宣传"快了十倍",而是建立自己的基准。


二、先建立 TypeScript 6 的性能基线

升级前记录四项数据:

bash 复制代码
全量类型检查时间
增量类型检查时间
峰值内存
CI 中的实际耗时

可以先使用系统自带的 time

bash 复制代码
/usr/bin/time -v \
  npx tsc \
  -p tsconfig.json \
  --noEmit

macOS 可以使用:

bash 复制代码
time npx tsc -p tsconfig.json --noEmit

Windows PowerShell:

bash 复制代码
Measure-Command {
  npx tsc -p tsconfig.json --noEmit
}

建议至少运行三次。

第一次通常包含磁盘缓存、依赖读取和初始化成本,不能只取第一次结果。

一个简单的 Node.js 测试脚本:

bash 复制代码
// scripts/benchmark-tsc.mjs

import { spawnSync } from 'node:child_process';
import process from 'node:process';

const command = process.argv[2];
const args = process.argv.slice(3);
const rounds = 5;
const results = [];

if (!command) {
  console.error(
    '用法:node scripts/benchmark-tsc.mjs <command> [args...]',
  );
  process.exit(1);
}

for (let round = 1; round <= rounds; round += 1) {
  const start = process.hrtime.bigint();

  const result = spawnSync(command, args, {
    stdio: 'inherit',
    shell: false,
  });

  const end = process.hrtime.bigint();
  const durationMs = Number(end - start) / 1_000_000;

  if (result.status !== 0) {
    console.error(`第 ${round} 次执行失败`);
    process.exit(result.status ?? 1);
  }

  results.push(durationMs);
  console.log(
    `第 ${round} 次:${durationMs.toFixed(2)} ms`,
  );
}

const sorted = [...results].sort((a, b) => a - b);
const average =
  results.reduce((sum, value) => sum + value, 0) /
  results.length;

console.log('\n测试结果:');
console.log(`最快:${sorted[0].toFixed(2)} ms`);
console.log(
  `中位数:${sorted[Math.floor(sorted.length / 2)].toFixed(2)} ms`,
);
console.log(`平均:${average.toFixed(2)} ms`);

运行:

bash 复制代码
node scripts/benchmark-tsc.mjs \
  npx \
  tsc -p tsconfig.json --noEmit

注意,这个脚本测的是进程总耗时,不是严格的编译器内部性能。

但它更接近开发者和 CI 实际等待的时间。


三、不要直接覆盖,先让 TypeScript 6 和 7 共存

TypeScript 7.0 暂时没有提供稳定的编程 API。依赖 typescript 包内部 API 的工具,可能仍然需要 TypeScript 6。

官方为此提供了 @typescript/typescript6 兼容包,可以让 TypeScript 6 与 TypeScript 7 同时存在。

可以将 package.json 调整为:

bash 复制代码
{
  "devDependencies": {
    "@typescript/native": "npm:typescript@^7",
    "typescript": "npm:@typescript/typescript6@^6"
  }
}

这里:

bash 复制代码
typescript

仍然指向 TypeScript 6,供依赖 Compiler API 的工具使用。

而:

bash 复制代码
@typescript/native

指向 TypeScript 7,并提供新的 tsc 可执行文件。

可以增加脚本:

bash 复制代码
{
  "scripts": {
    "typecheck:ts6": "tsc6 -p tsconfig.json --noEmit --stableTypeOrdering",
    "typecheck:ts7": "tsc -p tsconfig.json --noEmit"
  }
}

分别运行:

bash 复制代码
npm run typecheck:ts6
npm run typecheck:ts7

不要只对比退出码。

还应该对比:

bash 复制代码
错误数量
错误文件
声明文件
输出目录
构建时间
峰值内存
编辑器诊断结果

四、迁移前最好先通过 TypeScript 6

TypeScript 7 的类型检查和命令行行为,主要以 TypeScript 6 为兼容基线。

官方建议:项目先在 TypeScript 6 中启用 stableTypeOrdering,并且不要依赖 ignoreDeprecations 隐藏旧配置问题。能够在这种状态下干净通过的项目,迁移 TypeScript 7 通常会更顺利。

先运行:

bash 复制代码
npx tsc6 \
  -p tsconfig.json \
  --noEmit \
  --stableTypeOrdering

如果这里已经出现新错误,不要等切换 TypeScript 7 后再一起处理。

先在 TypeScript 6 下修复,能把"类型推断变化"和"原生编译器迁移问题"分开。


五、第一个常见坑:types 默认变成空数组

TypeScript 7 中,types 默认值变为:

bash 复制代码
[]

这意味着编译器不会再自动把所有可见的 @types 包加入全局环境。依赖 Node.js、Jest、Mocha 或其他全局类型的项目,需要显式声明。

升级后可能出现:

bash 复制代码
Cannot find name 'process'
Cannot find name 'describe'
Cannot find name 'expect'
Cannot find name 'Buffer'

修复方式:

bash 复制代码
{
  "compilerOptions": {
    "types": [
      "node",
      "jest"
    ]
  }
}

对于前后端混合 Monorepo,不建议在根配置里一次性加入全部类型。

可以拆成:

bash 复制代码
tsconfig.base.json
tsconfig.node.json
tsconfig.web.json
tsconfig.test.json

例如测试配置:

bash 复制代码
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "types": [
      "node",
      "vitest/globals"
    ]
  },
  "include": [
    "src/**/*.ts",
    "tests/**/*.ts"
  ]
}

这样可以避免测试框架的全局类型污染生产代码。


六、第二个常见坑:必须显式配置 rootDir

TypeScript 7 中,rootDir 默认指向 tsconfig.json 所在目录。

如果配置文件位于项目根目录,而代码全部放在 src,升级后输出目录结构可能变成:

bash 复制代码
dist/src/index.js

而旧项目预期的是:

bash 复制代码
dist/index.js

官方将 rootDirtypes 列为最容易让迁移项目感到意外的变化。

建议明确配置:

bash 复制代码
{
  "compilerOptions": {
    "rootDir": "./src",
    "outDir": "./dist"
  },
  "include": [
    "src/**/*.ts"
  ]
}

Monorepo 中每个子项目都应有自己的 rootDir

bash 复制代码
packages/
├── api/
│   ├── src/
│   └── tsconfig.json
├── shared/
│   ├── src/
│   └── tsconfig.json
└── web/
    ├── src/
    └── tsconfig.json

不要只依赖根配置自动推断。


七、第三个常见坑:默认配置更现代,也更严格

TypeScript 7 采用 TypeScript 6 的新默认值,包括:

bash 复制代码
strict = true
module = esnext
noUncheckedSideEffectImports = true
libReplacement = false
stableTypeOrdering = true

target 也会默认使用当前较新的稳定 ECMAScript 版本。

这意味着一个配置非常少的旧项目:

bash 复制代码
{
  "compilerOptions": {}
}

升级后行为可能出现明显变化。

对于存量项目,建议不要依赖默认值,把关键配置写明:

bash 复制代码
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noUncheckedSideEffectImports": true,
    "rootDir": "./src",
    "outDir": "./dist",
    "types": [
      "node"
    ]
  }
}

显式配置不仅是为了兼容。

也能避免未来版本再次调整默认值时,项目行为悄悄改变。


八、第四个常见坑:一批旧选项已经彻底不能用了

TypeScript 7 对 TypeScript 6 中已经弃用的部分配置直接报错。

比较常见的包括:

bash 复制代码
target: es5
moduleResolution: node
moduleResolution: node10
moduleResolution: classic
module: amd
module: umd
module: systemjs
module: none
baseUrl
downlevelIteration

同时:

bash 复制代码
esModuleInterop
allowSyntheticDefaultImports
alwaysStrict

也不能再通过设置为 false 恢复旧行为。

旧 Node.js 项目:

bash 复制代码
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  }
}

可以根据运行环境改成:

bash 复制代码
{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  }
}

使用 Vite、Webpack、Rspack 等打包器的前端项目,可以考虑:

bash 复制代码
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "paths": {
      "@/*": [
        "./src/*"
      ]
    }
  }
}

不要机械地把所有项目都改成 NodeNext

选择依据应该是:

bash 复制代码
代码最终由 Node.js 直接运行
还是交给 Bundler 处理

九、第五个常见坑:导入断言语法已经变化

旧代码可能使用:

bash 复制代码
import config from './config.json'
  assert { type: 'json' };

现在应该改成导入属性:

bash 复制代码
import config from './config.json'
  with { type: 'json' };

TypeScript 7 不再接受旧的 asserts 导入写法。

可以先全局搜索:

bash 复制代码
rg "assert\s*\{\s*type:" \
  src packages

再逐个确认运行时和打包器是否支持新的语法。

不要只让 TypeScript 编译通过,还要检查:

bash 复制代码
Node.js 版本
Bundler 版本
测试运行器
代码转换插件

是否能够正确执行。


十、并行参数不是越大越好

TypeScript 7 默认会创建 4 个类型检查 Worker。

可以通过:

bash 复制代码
tsc --checkers 8

增加类型检查并行度。

对于 Project References,可以通过:

bash 复制代码
tsc --build \
  --checkers 4 \
  --builders 2

控制并行构建项目的数量。官方也提供 --singleThreaded,用于调试、低资源环境或与外部并行系统配合。

但要注意:

bash 复制代码
checkers × builders

可能形成乘法级并发。

例如:

bash 复制代码
tsc --build \
  --checkers 4 \
  --builders 4

理论上可能同时出现多达 16 个类型检查 Worker。

在开发者 16 核、32GB 内存的电脑上可能很快。

放到只有 2 核、7GB 内存的 CI Runner 中,反而可能出现:

bash 复制代码
频繁 GC
内存不足
CPU 抢占
构建时间波动
进程被系统终止

建议准备三档参数。

本地高性能电脑:

bash 复制代码
tsc --build \
  --checkers 8 \
  --builders 2

普通 CI:

bash 复制代码
tsc --build \
  --checkers 2 \
  --builders 1

问题排查:

bash 复制代码
tsc --build \
  --singleThreaded

最终数值必须通过自己的项目测出来。


十一、用脚本自动寻找合适并发数

可以写一个简单测试脚本:

bash 复制代码
// scripts/benchmark-checkers.mjs

import { spawnSync } from 'node:child_process';

const candidates = [1, 2, 4, 6, 8];
const results = [];

for (const checkers of candidates) {
  const start = process.hrtime.bigint();

  const result = spawnSync(
    'npx',
    [
      'tsc',
      '-p',
      'tsconfig.json',
      '--noEmit',
      '--checkers',
      String(checkers),
    ],
    {
      stdio: 'ignore',
      shell: false,
    },
  );

  const end = process.hrtime.bigint();
  const durationMs =
    Number(end - start) / 1_000_000;

  if (result.status !== 0) {
    console.error(
      `checkers=${checkers} 执行失败`,
    );
    process.exit(result.status ?? 1);
  }

  results.push({
    checkers,
    durationMs,
  });

  console.log(
    `checkers=${checkers}:` +
    `${durationMs.toFixed(2)} ms`,
  );
}

results.sort(
  (left, right) =>
    left.durationMs - right.durationMs,
);

console.log(
  `\n当前机器最快配置:` +
  `--checkers ${results[0].checkers}`,
);

运行:

bash 复制代码
node scripts/benchmark-checkers.mjs

该结果只能代表当前机器。

开发者电脑和 CI 应分别测试,不要共用一套并发值。


十二、第六个常见坑:Vue、Svelte、Astro、MDX 暂时别强切

TypeScript 7.0 目前没有稳定的编程 API。

因此,需要把 TypeScript 嵌入自身编译器或语言服务的工具,暂时不能完整切换。

官方明确指出:

bash 复制代码
Vue
Svelte
Astro
MDX

相关工作流目前应继续使用 TypeScript 6。

Angular 项目可以使用 TypeScript 7 的 CLI 做项目级错误检查,但模板相关编辑器体验仍可能需要 TypeScript 6。

所以这些项目不要简单运行:

bash 复制代码
npm install -D typescript@latest

更稳妥的做法是双轨运行:

bash 复制代码
TypeScript 6:供框架插件和编程 API 使用
TypeScript 7:用于独立 CLI 类型检查和性能验证

等框架工具链明确宣布支持后,再切换默认版本。


十三、第七个常见坑:typescript-eslint 等工具可能仍依赖 6.x API

TypeScript 7.0 暂时不提供 Compiler API。

而很多工具会直接:

bash 复制代码
import ts from 'typescript';

调用编译器内部能力。

例如:

bash 复制代码
类型感知 ESLint
自定义 AST 工具
代码生成器
文档生成器
自定义 Transformer
内部类型分析脚本

这些工具不一定能立刻使用 TypeScript 7。

这也是为什么官方提供 TypeScript 6 兼容包,并推荐使用 npm Alias 让旧 API 和新 CLI 并存。

升级前可以搜索:

bash 复制代码
rg "from ['\"]typescript['\"]" \
  scripts tools packages

或者:

bash 复制代码
rg "require\(['\"]typescript['\"]\)" \
  scripts tools packages

如果项目代码直接调用了:

bash 复制代码
ts.createProgram()
ts.createSourceFile()
ts.transform()
ts.TypeChecker

就不能只测试 tsc 是否成功。

还要单独测试这些内部工具。


十四、第八个常见坑:JavaScript 与 JSDoc 项目变化更大

TypeScript 7 重构了 JavaScript 文件和 JSDoc 的分析方式,使其更接近 .ts 文件。

部分旧式 JSDoc 和 Closure 风格写法不再支持,例如:

bash 复制代码
把值直接当类型使用
旧式 @enum 行为
单独使用 ? 表示类型
通过 @class 把普通函数变成构造器
Closure 风格 function(string): void

这些变化主要影响:

bash 复制代码
allowJs
checkJs
大型 JavaScript 项目
依赖 JSDoc 类型的旧代码库

官方维护了专门的差异记录。纯 TypeScript 项目通常影响较小,但大量使用 JSDoc 的仓库需要单独建立测试清单。

例如旧写法:

bash 复制代码
/** @type {SomeRuntimeValue} */
let value;

如果 SomeRuntimeValue 是运行时变量,需要改成:

bash 复制代码
/** @type {typeof SomeRuntimeValue} */
let value;

不要因为项目文件扩展名是 .js,就认为 TypeScript 7 与自己无关。


十五、推荐的完整迁移顺序

不要在一个 PR 中同时升级编译器、修改构建系统、调整模块格式和修复全部类型错误。

更稳的迁移顺序是:

第一步:固定 TypeScript 6 基线

bash 复制代码
npm install -D typescript@^6
npx tsc --noEmit --stableTypeOrdering

修复全部弃用配置和新增类型错误。

第二步:显式补齐关键配置

bash 复制代码
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "rootDir": "./src",
    "types": [
      "node"
    ]
  }
}

第三步:安装双版本

bash 复制代码
{
  "devDependencies": {
    "@typescript/native": "npm:typescript@^7",
    "typescript": "npm:@typescript/typescript6@^6"
  }
}

第四步:在 CI 并行检查

bash 复制代码
- name: TypeScript 6 compatibility
  run: npm run typecheck:ts6

- name: TypeScript 7 validation
  run: npm run typecheck:ts7

第五步:对比声明文件

如果发布 npm 包,分别生成声明:

bash 复制代码
rm -rf artifacts/ts6 artifacts/ts7

npx tsc6 \
  -p tsconfig.build.json \
  --declaration \
  --emitDeclarationOnly \
  --outDir artifacts/ts6

npx tsc \
  -p tsconfig.build.json \
  --declaration \
  --emitDeclarationOnly \
  --outDir artifacts/ts7

diff -ru \
  artifacts/ts6 \
  artifacts/ts7

注意,类型排序变化可能产生无害 Diff,需要人工区分:

bash 复制代码
纯顺序变化
真实类型变化
导出缺失
泛型推断改变

第六步:单独调优并行参数

分别在开发机和 CI 中测试:

bash 复制代码
--checkers 1
--checkers 2
--checkers 4
--checkers 8

Monorepo 再测试不同的 --builders

第七步:观察一到两周

重点记录:

bash 复制代码
CI 平均耗时
CI P95 耗时
内存峰值
编辑器崩溃
类型错误差异
声明文件差异
框架插件异常

第八步:再切换默认版本

确认稳定后,再将 TypeScript 7 设为默认 typescript


十六、哪些项目最值得优先升级?

优先级较高:

bash 复制代码
大型 TypeScript Monorepo
Project References 项目
CI 类型检查超过一分钟
编辑器打开项目非常慢
经常使用查找引用和重命名
拥有多核开发机和 CI Runner

建议暂缓:

bash 复制代码
严重依赖 Compiler API
拥有大量自定义 Transformer
Vue、Svelte、Astro、MDX 工具链未确认兼容
Angular 项目高度依赖模板语言服务
大量使用旧式 JSDoc
仍需输出 ES5
仍使用 AMD、UMD 或 SystemJS

TypeScript 7 不是所有项目都必须在发布当天升级。

对小项目而言,类型检查从 2 秒降低到 0.5 秒,实际价值可能有限。

对一个 CI 类型检查需要 8 分钟、每天运行数百次的 Monorepo,收益则非常明显。


十七、别只看编译速度,还要计算团队节省的时间

假设一个团队有 20 名开发者:

bash 复制代码
每人每天类型检查 15 次
原耗时 30 秒
升级后耗时 5 秒

每天节省:

bash 复制代码
20 × 15 × 25 秒
= 7500 秒
≈ 125 分钟

一个月按 22 个工作日计算:

bash 复制代码
125 × 22
= 2750 分钟
≈ 45.8 小时

还没有计算:

bash 复制代码
编辑器首次加载
查找引用
自动补全
重命名
CI 排队
PR 合并等待

这也是 TypeScript 7 对大型团队更有价值的原因。

但前提是升级没有引入新的工具链故障。

所以迁移目标应该是:

在兼容性可控的前提下,缩短整个开发反馈循环。

而不是只追求一张漂亮的编译器跑分截图。


十八、AI 编程时代,类型检查速度反而更重要

现在使用 AI 编程工具时,一次任务可能同时修改十几个文件。

代码生成速度变快后,新的瓶颈往往变成:

bash 复制代码
类型检查
Lint
测试
构建
人工 Review

模型一分钟写完代码,但项目类型检查需要五分钟,开发反馈循环仍然很慢。

TypeScript 7 的价值并不是让 AI 更会写代码。

而是让每次生成后的验证更快:

bash 复制代码
AI 修改代码
↓
立即运行类型检查
↓
快速发现跨文件错误
↓
继续修正
↓
进入测试和 Review

长期使用 ChatGPT Plus、Claude Pro、Cursor、Kiro 等工具时,可以通过 gpt68.com 了解相关第三方 AI 会员充值服务;不过,对开发团队而言,工具订阅只是准备,编译、测试和 Review 的反馈速度才真正决定 AI 编程效率。


总结

TypeScript 7.0 最明显的变化,是原生编译器和多线程带来的大幅提速。

但真正决定项目能不能顺利升级的,是下面这些问题:

bash 复制代码
types 是否显式配置
rootDir 是否固定
旧 moduleResolution 是否清理
baseUrl 是否移除
运行环境是否支持新模块方案
框架插件是否兼容
Compiler API 工具如何继续运行
checkers 和 builders 是否适合当前机器
JSDoc 项目是否存在行为变化

最稳的迁移方式不是直接覆盖。

而是:

bash 复制代码
TypeScript 6 建立兼容基线
TypeScript 6 与 7 双版本运行
对比错误和声明文件
单独测试插件与内部工具
根据机器调优并发
观察 CI 和编辑器稳定性
最后再切换默认版本

TypeScript 7 确实可能让大型项目的类型检查从"需要等待"变成"接近即时反馈"。

但只有把兼容性问题提前解决,这部分性能提升才会真正转化为研发效率。

相关推荐
天天有money15 小时前
API中转站在社媒矩阵里的价值:多平台文案如何统一改写
gpt·线性代数·ai·chatgpt·矩阵
LDZKKJ16 小时前
OpenAI暂停GPT-6训练:AI行业从“竞速“到“刹车“的分水岭
人工智能·gpt·语言模型·chatgpt·transformer
天天摸鱼的java工程师18 小时前
公司取消前端岗后,做了 10 年 Java 的我,第一次认真拥抱 AI
前端·后端·openai
西安小哥18 小时前
AI与万物融合:从顶层设计到草根落地的全景图景
aigc·openai
仙逆GPT1 天前
Codex定时任务怎么设置?ChatGPT Plus用Worktree自动巡检项目
chatgpt·定时任务·codex·git worktree·chatgpt plus
crary,记忆1 天前
Claude Code vs Claude Co-Work vs Gemini vs ChatGPT:全方位深度对比
人工智能·学习·chatgpt·ai编程
Miracleeee2 天前
OpenAI 官方教你怎么用 Codex,其实是在教你怎么写一份「Skill」
aigc·openai
SQDN2 天前
Chatbox 1.22.1 获取不到模型?先验 /models,再对齐精确 model ID
人工智能·测试工具·机器学习·chatgpt·json
Zeeland2 天前
Agent 能完成一个任务,但它能持续追一个三个月的目标吗?
人工智能·github·openai