TypeScript 6 正式发布:最值得关注的重点、坑点与升级建议
TypeScript 6.0 已经在 2026 年 3 月 23 日正式发布。
如果只看一句话总结,那就是:
TS6 不是一个“炫技型”大版本,而是一个为 TypeScript 7 铺路的过渡版本。
它最重要的意义,不是突然多了很多全新语法,而是把很多旧时代配置和兼容包袱清理掉,同时把默认值往“现代 JavaScript / ESM / Bundler / Evergreen Runtime”这条路上统一。
所以这次更新,真正值得关注的不是“新语法有多酷”,而是“默认行为变了哪些、你的项目会不会直接报错”。
这篇文章我尽量只讲最重要的部分,并配上简单示例,方便你快速判断:
- TS6 值不值得升
- 升级最容易踩哪些坑
- 有哪些新能力值得立刻用起来
一、先说结论:TS6 最重要的 3 件事
1. TS6 是 TS7 的桥梁版本
官方已经讲得很明确:TypeScript 6.0 是最后一个基于当前 JavaScript 代码库的正式大版本,后面的 TypeScript 7 会基于新的 Go 原生实现继续演进。
这意味着 TS6 的很多变化,核心目标都不是“单独优化自己”,而是:
- 尽量和 TS7 行为对齐
- 提前清理不适合继续保留的老配置
- 降低未来迁移到 TS7 的成本
如果你后面打算跟进 TS7,那 TS6 基本就是绕不过去的一站。
2. 这次最有体感的变化,是默认值和配置策略
TS6 对很多编译配置的默认行为做了调整,比如:
strict默认变成truemodule默认变成esnexttarget默认跟随当前年份的 ES 版本,目前是es2025types默认变成[]rootDir默认变成当前tsconfig.json所在目录
这类变化的特点是:不一定看起来“新”,但非常可能影响老项目。
3. 语法层面的亮点有,但都比较务实
TS6 也有一些很实用的新能力,比如:
- 更好的方法推断
- 支持
#/子路径导入 - 新增
Temporal类型 - 支持
es2025 RegExp.escape、Map.getOrInsert等新标准库类型
这些都不是“革命性语法”,但胜在能很快落地。
二、最值得关注的几个新变化
1. 对象里的函数,推断终于没那么别扭了
这是我认为最容易被低估的一项改进。
以前 TypeScript 在一种很常见的场景里会有点“看人下菜碟”:
- 如果你在对象里写的是箭头函数,推断通常没问题
- 但如果你写的是更自然的对象方法语法,推断有时就会突然变差
比如下面这两种写法,看起来只是长得不一样:
const obj1 = {
consume: (y) => y.toFixed()
};
const obj2 = {
consume(y) {
return y.toFixed();
}
};
很多人会更喜欢第二种,因为它更像正常写对象。
但在旧版本里,第二种写法在某些泛型场景下,TypeScript 反而更容易“犯迷糊”,把参数推成 unknown。
例如:
declare function callIt<T>(obj: {
produce: (x: number) => T;
consume: (y: T) => void;
}): void;
callIt({
consume(y) {
return y.toFixed();
},
produce(x: number) {
return x * 2;
},
});
在旧行为里,上面这种写法里的 y 可能会被推成 unknown。
TS6 修了这个问题:如果这个对象方法里根本没有用到 this,那 TypeScript 就别再自己吓自己了,该正常推断就正常推断。
这带来的直接好处是:
- 你可以更放心地写对象方法
- 泛型推断更稳定
- 少写一些“本来不该补”的显式类型
如果你平时喜欢写配置对象、工具对象,或者各种对象式 API,这个改动会舒服很多。
2. 终于支持 #/ 子路径导入
Node 的 imports 字段本来就支持子路径导入,但以前你必须写成像 #root/* 这种形式,不能直接从 #/ 开始。
TS6 跟进了 Node 的新能力,现在在 moduleResolution: "nodenext" 或 moduleResolution: "bundler" 下,可以直接这样配:
{
"name": "my-package",
"type": "module",
"imports": {
"#/*": "./src/*"
}
}
然后代码里这样写:
import { sum } from "#/utils/sum.js";
这件事的价值在于:
你终于可以少写一堆 ../../.. 了,而且写法比传统相对路径更稳定。
如果你现在本来就在用 bundler、Node ESM 或 Bun,这个特性很值得考虑。
3. types 默认变成 [],性能更好,但也是最容易踩坑的地方之一
这是 TS6 升级时最需要注意的改动之一。
过去,TypeScript 会默认把 node_modules/@types 里很多声明包自动扫进来。
这样虽然“省心”,但代价也很明显:
- 多项目仓库里会加载大量没必要的类型
- 构建和编辑器响应都会变慢
- 全局类型来源不够可控
TS6 现在把默认值改成了:
{
"compilerOptions": {
"types": []
}
}
如果你的项目依赖 Node 全局类型、测试框架全局类型等,就需要显式写出来:
{
"compilerOptions": {
"types": ["node", "jest"]
}
}
如果你升级后突然看到这些报错:
Cannot find name 'process'Cannot find name 'describe'Cannot find module 'fs'
那大概率就是这里。
我的建议很简单:
Node项目:先加"types": ["node"]- 有测试框架:再补
jest、mocha、vitest/globals对应配置 - 不要偷懒回退成
"types": ["*"],除非你真的只想临时救火
4. rootDir 默认变成当前目录,输出路径可能会变
TS6 以前会推断一个公共源目录作为 rootDir。
现在默认更简单了:直接把 tsconfig.json 所在目录当成 rootDir。
这会导致一个很典型的问题:
假设你的项目结构是:
project/
tsconfig.json
src/
index.ts
你以前可能输出的是:
dist/index.js
升级后如果没显式配置 rootDir,可能会变成:
dist/src/index.js
解决办法也很直接:
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["src"]
}
如果你升级后发现打包产物目录层级变深了,优先看这个配置。
5. TS6 支持 es2025 和更多新标准库类型
TS6 新增了 es2025 的 target / lib 支持。
虽然 ES2025 本身没有那种“看得见摸得着”的全新语法炸点,但它补上了不少新标准库类型,比如:
RegExp.escapePromise.tryIterator方法Set方法
例如 RegExp.escape 终于不用手写转义函数了:
function matchWholeWord(word: string, text: string) {
const escaped = RegExp.escape(word);
const regex = new RegExp(`\\b${escaped}\\b`, "g");
return text.match(regex);
}
这种 API 的意义不在于“多高级”,而在于它让很多过去靠手写工具函数的逻辑,终于能收敛到标准库。
6. 内置了 Temporal 类型
如果你之前关注过 JavaScript 日期时间 API 的演进,那应该知道 Temporal 这些年一直很受期待。
TS6 现在已经内置了它的类型定义。只要你使用 esnext 相关 lib,就能直接获得类型支持:
const yesterday = Temporal.Now.instant().subtract({
hours: 24,
});
const tomorrow = Temporal.Now.instant().add({
hours: 24,
});
这不代表所有运行时已经完全原生可用,但至少在类型层面,TS 已经把它视为现代 JavaScript 的正式方向之一。
三、升级 TS6 时最容易踩的坑
如果你没时间把发布说明从头看到尾,那至少记住下面几个点。
1. strict 现在默认是 true
如果你的项目之前没有显式写过 strict,升级后可能会突然多出一批类型错误。
你有两个选择:
- 直接接受新默认值,顺手把类型债一起还掉
- 先显式写回
"strict": false,分阶段迁移
如果是老项目,我更推荐先稳住:
{
"compilerOptions": {
"strict": false
}
}
等升级完成后,再逐步往回收紧。
2. baseUrl 不再作为模块查找根目录
这是一个很关键的兼容性变化。
如果你以前这样写:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@app/*": ["app/*"]
}
}
}
TS6 推荐改成更明确的写法:
{
"compilerOptions": {
"paths": {
"@app/*": ["./src/app/*"]
}
}
}
也就是说,别再指望 baseUrl 作为一个隐式前缀去兜底。
3. moduleResolution: "classic" 已经被移除
如果你还在用:
{
"compilerOptions": {
"moduleResolution": "classic"
}
}
那就该换了。
官方给出的现代方向很明确:
bundlernodenext
大多数现代前端项目,我会优先考虑 bundler;
Node ESM 项目,则优先考虑 nodenext。
4. esModuleInterop: false 这条老路也走不通了
TS6 不再允许把下面这些设置成 false:
esModuleInteropallowSyntheticDefaultImports
也就是说,和 CommonJS 的互操作行为,现在默认就按更安全、也更现代的方式走。
过去你可能这么写:
import * as express from "express";
现在很多场景下更推荐:
import express from "express";
如果你项目里还大量依赖旧导入方式,升级时最好跑一轮检查。
5. outFile 被彻底移除了
如果你还在靠 TypeScript 自己把多个输入文件拼成一个输出文件,那 TS6 会直接告诉你:别这么干了。
现在这件事应该交给 bundler:
esbuildViteRollupWebpackParcel
TS 团队的态度很明确:TypeScript 更应该专注在类型检查和声明生成,而不是继续兼任 bundler。
6. 旧的 import assertions 写法要改成 with
以前这样写:
import data from "./data.json" asserts { type: "json" };
现在要改成:
import data from "./data.json" with { type: "json" };
这个改动不复杂,但如果你项目里有 JSON import、WASM import、CSS module attribute 之类的实验性写法,升级前最好全局搜一下。
7. 在有 tsconfig.json 的目录里直接跑 tsc foo.ts,现在会报错
这是一个很容易忽略,但实际非常常见的变化。
以前很多人会在项目目录里顺手执行:
tsc src/index.ts
但如果当前目录里已经有 tsconfig.json,TS6 现在会直接提示你:
这个配置文件不会被加载。
如果你本来就是想忽略配置、只按默认行为编译单个文件,那需要显式写成:
tsc --ignoreConfig src/index.ts
这个改动的目的其实很合理,就是避免“明明项目有配置,但命令行行为和你想的不一样”这种隐性坑。
四、TS6 到底值不值得升?
我的判断是:
值得尽快升级的人
- 你正在维护现代前端项目
- 你已经使用 ESM / bundler / NodeNext
- 你准备后面跟 TS7
- 你本来就想顺手清理旧
tsconfig
这类项目升级 TS6 的收益是明确的,因为配置方向和生态方向是一致的。
可以先观察一下的人
- 很老的历史项目
- 有大量自定义构建链
- 还依赖
classic、outFile、baseUrl老行为 - 有很多隐式全局类型和非严格模式代码
这类项目不是不能升,而是最好把它当成一次小型迁移项目来做,不要只改个版本号就上线。
五、一个更实用的升级顺序
如果你准备从 TS5.x 升到 TS6,我建议按这个顺序来:
- 先升级依赖,但保守保留旧配置行为。
- 显式补上
strict、rootDir、types等关键配置,先让结果稳定。 - 搜索并替换明显废弃项,比如
asserts、moduleResolution: "classic"、outFile。 - 检查
baseUrl和paths,避免隐式路径查找失效。 - 最后再考虑吃掉 TS6 的新默认值,而不是一开始就全盘接受。
一个比较稳的过渡型 tsconfig.json 可以像这样:
{
"compilerOptions": {
"target": "es2025",
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"rootDir": "./src",
"outDir": "./dist",
"types": ["node"]
},
"include": ["src"]
}
如果你只是想先压住过渡期告警,也可以临时加上:
{
"compilerOptions": {
"ignoreDeprecations": "6.0"
}
}
但这只是过渡手段。因为官方已经明确说了:这些废弃项到了 TS7 不会再被支持。
六、最后
看完官方文档之后,我对 TS6 的感受其实很明确:
它不是那种“看完让人立刻兴奋到想重写项目”的版本,
但它很像一次必要的基础设施升级。
如果你只盯着“有没有惊艳语法”,会觉得 TS6 好像没那么炸;
但如果你站在未来一两年的工程演进上看,它其实非常重要。
因为从 TS6 开始,TypeScript 的官方态度已经很清楚了:
- 拥抱现代 ESM
- 拥抱 bundler
- 拥抱更严格的默认值
- 清理旧时代兼容包袱
- 为 TS7 的原生化铺平道路
所以我的建议是:
新项目可以直接按 TS6 的思路建,老项目则应该尽早做一次有计划的迁移。
参考资料
- 官方发布说明:Announcing TypeScript 6.0
- 官方 GitHub Release:microsoft/TypeScript Releases
- 官方背景说明:Progress on TypeScript 7 – December 2025