TypeScript 6.0 正式发布:为原生速度的 7.0 铺路 的文章头图

TypeScript 6.0 正式发布:为原生速度的 7.0 铺路

微软 TypeScript 团队已于 2026 年 3 月 23 日发布 TypeScript 6.0 正式版。这个版本的核心意义不只是新增几个 API 类型,而是为即将到来的原生 TypeScript 7.0 做迁移铺垫。本文整理了 6.0 的关键更新、默认值变化、弃用项以及升级时最值得优先处理的配置调整。

微软 TypeScript 团队在 2026 年 3 月 23 日发布了 TypeScript 6.0 正式版。这个版本最值得关注的地方,不是某一个单独的新语法,而是它的角色已经非常明确: 它是 TypeScript 5.9 到 TypeScript 7.0 之间的过渡桥梁。

本文基于官方公告整理改写: Announcing TypeScript 6.0

如果你已经在用 TypeScript,升级命令还是熟悉的这一条:

npm install -D typescript

一句话看懂 TypeScript 6.0

TypeScript 团队已经明确表示,6.0 很可能是最后一个基于现有 JavaScript 代码库的正式版本。后面的 TypeScript 7.0,会建立在一套新的 Go 代码库之上,目标是利用原生执行速度和共享内存多线程,把编译器与语言服务的性能再往前推一大步。

所以 6.0 的思路很清楚:

  • 一方面继续保持稳定可用,今天就能升级。
  • 另一方面尽量让配置、类型顺序、模块解析和默认行为逐步向 7.0 靠拢。

换句话说,如果你准备将来上 TypeScript 7.0,那么现在把项目先迁到 6.0,会轻松很多。

Beta 和 RC 之后又改了什么

正式版相比 Beta 和 RC,还有几处值得注意的收尾调整:

  • 泛型调用中的函数表达式类型检查又收紧了一些,尤其是泛型 JSX 场景。这通常能帮你更早发现 bug,但也意味着少数地方需要手动补显式类型参数。
  • import ... assert {...} 的弃用范围进一步扩大到了 import() 调用。
  • DOM 类型继续跟进最新 Web 标准,同时也补了一些 Temporal 相关调整。

这些变化的共同方向都很明显: 尽量跟未来的 TypeScript 7.0 行为保持一致。

这次最值得关注的更新

1. 不使用 this 的方法,类型推断终于不再吃亏

这是这次最实用的一处体验优化。

以前在泛型推断里,如果你用的是对象方法语法,而不是箭头函数语法,TypeScript 可能会因为方法默认带有隐式 this,把它当成“上下文敏感函数”,从而错过更好的推断时机。结果就是: 同样的逻辑,箭头函数没问题,方法写法却可能把参数推成 unknown

TypeScript 6.0 现在会更聪明一点:

  • 如果函数里根本没有真正使用 this
  • 那它就不会再被当成需要特殊回避的上下文敏感函数

这意味着很多原来因为写法不同而触发的莫名其妙推断失败,在 6.0 里都能自然通过。

2. Node 子路径导入现在支持 #/

如果你之前用过 Node 的 imports 字段,应该对这种写法不陌生:

{
  "name": "my-package",
  "type": "module",
  "imports": {
    "#/*": "./dist/*"
  }
}

以前大家往往得写成 #root/*#src/* 这种多带一层名字的形式。现在 Node 新版本已经支持以 #/ 直接开头,TypeScript 6.0 也在 --moduleResolution nodenext--moduleResolution bundler 下跟进支持了这套行为。

如果你一直习惯在打包器里写 @/ 做路径别名,那这次更新会让 Node 子路径导入更顺手,也更统一。

3. --moduleResolution bundler 终于可以和 --module commonjs 一起用

这项改动很务实。

过去 bundler 解析策略只能搭配 esnextpreserve,但现实里的很多老项目并不是一步到位切到纯 ESM,它们往往还在 CommonJS 和现代打包链之间过渡。

TypeScript 6.0 放开这个组合之后,升级路径清晰了不少:

  • Web 打包项目或 Bun 项目,优先考虑 bundler
  • 直接跑在 Node.js 上的项目,优先考虑 nodenext

对于不少还在从旧的 node / node10 解析策略迁移的仓库来说,这个调整很关键。

4. 新增 --stableTypeOrdering,专门帮你对齐 6.0 和 7.0

这是一个很“迁移导向”的新选项。

TypeScript 过去会按类型被发现的顺序分配内部 ID,再用这些 ID 去影响联合类型、属性顺序甚至声明输出顺序。平时你不一定在意,但一旦你开始比对 .d.ts 产物,或者检查 6.0 与 7.0 的输出差异,这种“声明顺序影响最终结果”的行为会制造很多噪音。

TypeScript 7.0 为了支持并行类型检查,会改用更稳定、可重复的排序方式。于是 6.0 先给了你一个过渡开关:

tsc --stableTypeOrdering

打开它之后,6.0 的类型排序会更接近 7.0,便于你提前发现真正的问题,而不是被无意义的顺序变化干扰。

不过官方也提醒了,这个选项可能让类型检查速度下降,某些代码库甚至会慢到 25% 左右,所以它更适合用来诊断和迁移,而不是长期常驻。

5. targetlib 现在支持 es2025

虽然 ES2025 本身没有新增 JavaScript 语法,但它补进了不少标准库类型,比如:

  • RegExp.escape
  • Promise.try
  • Iterator 方法
  • Set 方法

这类变化不一定会立刻改变你的业务代码写法,但它意味着 TypeScript 对最新 ECMAScript 标准库的跟进又往前走了一步。

6. TemporalMap upsertRegExp.escape 都补进来了

这一批更新的共同特点是: 不是语法层面的大新闻,但非常贴近日常开发。

先说 Temporal。这个提案终于走到 stage 4,TypeScript 6.0 也内置了对应类型。只要你使用 --target esnext 或在 lib 里加入 esnext / esnext.temporal,就可以直接拿到类型支持:

const yesterday = Temporal.Now.instant().subtract({ hours: 24 });
const tomorrow = Temporal.Now.instant().add({ hours: 24 });

console.log(`Yesterday: ${yesterday}`);
console.log(`Tomorrow: ${tomorrow}`);

再看 Map / WeakMap 的 upsert 方法。很多人都写过“没有就插入默认值”的样板代码,现在官方类型里直接补上了:

  • getOrInsert
  • getOrInsertComputed

像这样:

function processOptions(options: Map<string, unknown>) {
  const strictValue = options.getOrInsert("strict", true);
  return strictValue;
}

还有一个很容易被忽略但很实用的更新,是 RegExp.escape()

function matchWholeWord(word: string, text: string) {
  const escapedWord = RegExp.escape(word);
  const regex = new RegExp(`\\b${escapedWord}\\b`, "g");
  return text.match(regex);
}

以前这类正则转义逻辑很多项目都在自己造轮子,现在终于可以少写一点重复代码了。

7. dom 现在默认就包含可迭代类型

以前很多人第一次在浏览器环境里遍历 NodeList 时,都会被这个配置坑一下:

{
  "compilerOptions": {
    "lib": ["dom", "dom.iterable"]
  }
}

TypeScript 6.0 之后,lib.dom.d.ts 已经直接把 dom.iterabledom.asynciterable 的内容合并进去了。也就是说,现代浏览器项目里你通常只写 dom 就够了。

这不是什么爆炸性升级,但确实能少一个常见的配置困惑点。

升级到 TypeScript 6.0 前,先看这几处默认值变化

这部分很重要。官方这次不是只加功能,而是顺手把很多“更符合现代项目现实”的默认行为也一起往前推了。

strict 现在默认就是 true

如果你本来就在用严格模式,那没有任何影响。反过来,如果你过去是靠默认的宽松行为在跑,升级后就要显式写上:

{
  "compilerOptions": {
    "strict": false
  }
}

module 默认变成 esnext

这个变化本质上是在承认一个现实: 现在的新项目大多都在往 ESM 走。

target 默认跟到当前支持的年度版本

目前对应的是 es2025。官方的意思也很直接: 面向现代运行时的项目,不应该再默认往过老的标准降级。

noUncheckedSideEffectImports 默认开启

纯副作用导入里的拼写错误,现在更容易被提早发现。

libReplacement 默认变成 false

这是一个偏性能向的调整,主要是为了减少无意义的模块解析和 watch 负担。

rootDir 现在默认是 tsconfig.json 所在目录

这条很容易把老项目打疼。

如果你之前依赖 TypeScript 自动推断公共源码根目录,升级到 6.0 以后,输出目录结构可能会突然变得不一样。比如你本来期望输出到 ./dist/index.js,结果却变成 ./dist/src/index.js

更稳妥的做法,是直接显式写出来:

{
  "compilerOptions": {
    "rootDir": "./src"
  },
  "include": ["./src"]
}

types 默认值现在是空数组 []

这也是影响范围很大的一项变化。

过去 TypeScript 会默认把 node_modules/@types 下面能枚举到的包都尽量扫进来,这虽然方便,但在现在这种依赖树复杂、工作区庞大的项目里,非常容易拖慢构建速度。

TypeScript 6.0 改成了保守策略: 默认什么都不帮你自动加。

也就是说,如果你项目里需要 Node、Jest、Mocha 或 Bun 的全局类型,最好自己显式声明:

{
  "compilerOptions": {
    "types": ["node", "jest"]
  }
}

如果你只是想先恢复旧行为,也可以临时写:

{
  "compilerOptions": {
    "types": ["*"]
  }
}

但从长期看,显式列出真正需要的类型包,会更快,也更可控。

这批弃用项,最好现在就开始清

TypeScript 6.0 最“有迁移意味”的部分,其实是下面这批弃用和行为调整。官方已经说得很明确: 它们在 6.0 里还能靠 "ignoreDeprecations": "6.0" 暂时压住警告,但到了 TypeScript 7.0,会直接移除。

比较需要优先关注的包括:

  • target: es5 被弃用,最低目标版本抬到 es2015
  • --downlevelIteration 失去意义,因为它本来就是围绕 ES5 降级输出设计的
  • --moduleResolution node / node10 被弃用,Node 项目建议转 nodenext,打包项目建议转 bundler
  • --module amdumdsystemjsnone 不再是推荐方向
  • --baseUrl 被弃用,如果你主要是给 paths 做前缀,现在更推荐把路径前缀直接写进 paths
  • moduleResolution: classic 应该彻底迁走
  • esModuleInterop: falseallowSyntheticDefaultImports: false 这类“坚持旧互操作行为”的配置不再推荐
  • alwaysStrict: false 不再是未来方向,6.0 默认把代码视作严格模式
  • outFile 正式退出舞台,打包这件事交给 Vite、esbuild、Rollup、Webpack 之类工具就好
  • 老式 module Foo {} 命名空间语法要改成 namespace Foo {}
  • import ... asserts {} 语法被弃用,要换成 with
  • /// <reference no-default-lib="true"/> 不再推荐
  • 在存在 tsconfig.json 的目录里直接执行 tsc foo.ts,现在会报错,需要用 --ignoreConfig

其中最容易在代码里直接踩到的,是导入属性这类语法变化。旧写法:

import blob from "./data.json" asserts { type: "json" };

新写法:

import blob from "./data.json" with { type: "json" };

给准备升级的项目一个务实清单

如果你准备把项目迁到 TypeScript 6.0,我更建议按下面这个顺序处理:

  1. 先把 types 显式列出来,避免一升级就出现一堆 processfsdescribe 找不到的错误。
  2. 再确认 rootDir 是否需要手动指定,尤其是输出路径发生变化的项目。
  3. 检查模块解析策略,Node 项目优先考虑 nodenext,打包链项目优先考虑 bundler
  4. assertsbaseUrl、旧模块系统这些明显会在 7.0 被清掉的配置先收拾掉。
  5. 如果你要对比 6.0 和未来 7.0 的产物差异,可以临时打开 --stableTypeOrdering,减少无意义噪音。

如果你只是想先把升级跑通,又暂时来不及改完所有弃用项,也可以先用:

{
  "compilerOptions": {
    "ignoreDeprecations": "6.0"
  }
}

但这只是缓冲带,不是终点。

TypeScript 6.0 值不值得现在升级

我的判断是: 值得,而且越早越好。

原因并不是 6.0 本身塞进了多少“必须立刻拥有”的新能力,而是它把未来 TypeScript 7.0 的迁移成本,提前拆成了今天就能处理的小步骤。

你可以把它理解成一次“提前整理项目配置债务”的版本:

  • 补齐 types
  • 固定 rootDir
  • 调整模块解析策略
  • 清理过时配置
  • 适应更现代的默认值

等这些事情都做完,再去尝试 TypeScript 7.0 的 native preview,你的阻力会小很多。

总之,TypeScript 6.0 不是一个“炫技型大版本”,而是一个非常工程化、非常现实的大版本。它没有刻意堆很多噱头,而是在认真帮整个生态给原生版 TypeScript 7.0 铺路。

如果你的项目已经在 5.x 上稳定运行,现在确实可以开始规划升级了。

关于

关注我获取更多资讯

月球基地博客公众号二维码,扫码关注获取更多 AI 与编程资讯
📢 公众号
月球基地博客作者个人微信二维码,扫码交流 AI 与编程话题
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计