微软 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 解析策略只能搭配 esnext 或 preserve,但现实里的很多老项目并不是一步到位切到纯 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. target 和 lib 现在支持 es2025
虽然 ES2025 本身没有新增 JavaScript 语法,但它补进了不少标准库类型,比如:
RegExp.escapePromise.tryIterator方法Set方法
这类变化不一定会立刻改变你的业务代码写法,但它意味着 TypeScript 对最新 ECMAScript 标准库的跟进又往前走了一步。
6. Temporal、Map upsert 和 RegExp.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 方法。很多人都写过“没有就插入默认值”的样板代码,现在官方类型里直接补上了:
getOrInsertgetOrInsertComputed
像这样:
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.iterable 和 dom.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 amd、umd、systemjs、none不再是推荐方向--baseUrl被弃用,如果你主要是给paths做前缀,现在更推荐把路径前缀直接写进pathsmoduleResolution: classic应该彻底迁走esModuleInterop: false和allowSyntheticDefaultImports: 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,我更建议按下面这个顺序处理:
- 先把
types显式列出来,避免一升级就出现一堆process、fs、describe找不到的错误。 - 再确认
rootDir是否需要手动指定,尤其是输出路径发生变化的项目。 - 检查模块解析策略,Node 项目优先考虑
nodenext,打包链项目优先考虑bundler。 - 把
asserts、baseUrl、旧模块系统这些明显会在 7.0 被清掉的配置先收拾掉。 - 如果你要对比 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 上稳定运行,现在确实可以开始规划升级了。
关于
关注我获取更多资讯