前端开发 · 2026年2月26日

TypeScript 6.0 Beta实测:最后一个JS版本,为Go重写铺路

TypeScript 6.0 Beta在2月11号发了,这个版本很特殊——它是最后一个用JavaScript写的TypeScript编译器版本。下一个大版本TypeScript 7.0会用Go重写,利用原生代码和多线程并行来提速。6.0本质上是从JS时代到Go时代的过渡桥梁,很多改动都是为了让你提前适配7.0。我第一时间装上跑了一圈,记录下实际体验和踩坑。

安装和第一个惊喜

npm install -D typescript@beta

确认版本:

npx tsc --version# Version 6.0.0-beta

装完随手建个项目跑一下,第一个坑就来了。写了个简单的函数:

function bar(x) { return x; }

直接报错:

error TS7006: Parameter 'x' implicitly has an 'any' type.

原因是strict现在默认为true了。以前不写strict配置默认是false,现在反过来了。如果你的老项目没显式写"strict": true,升级后会多出一堆类型错误。解决方案:在tsconfig.json里显式加"strict": false。但说实话,都2026年了,不开strict的项目确实该反思一下了。

默认值大改:几乎每个老项目都会踩

6.0改了一堆默认值,这是最容易出问题的地方。我整理了一张表:

选项 旧默认值 新默认值 影响
strict false true 没显式配的项目会多很多类型错误
module commonjs esnext CJS项目需要显式指定
target es3 es2025 不再默认降级编译
rootDir 自动推断 tsconfig.json所在目录 输出目录结构可能变化
types [“*”](扫描全部) [](空) 需要显式声明@types包
noUncheckedSideEffectImports false true 副作用import拼写错误会报错

其中rootDir的变化最坑。实测如下:假设项目结构是:

project/  tsconfig.json  src/    index.ts

tsconfig.json里只写了"include": ["./src"],没有显式设rootDir。以前TS会自动推断rootDir为./src,输出到dist/index.js。现在6.0默认rootDir是tsconfig.json所在目录,输出变成了dist/src/index.js,而且会报一个错误:

error TS5011: The common source directory of 'tsconfig.json' is './src'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout.Visit https://aka.ms/ts6 for migration information.

修复很简单,显式写上rootDir:

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

types默认改为空数组也很关键。以前不写types,TS会扫描node_modules/@types下所有包自动引入。现在默认不引入任何东西,你需要显式声明:

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

不然连console.log都用不了(因为console类型在@types/node里)。想恢复旧行为可以写"types": ["*"],但官方不推荐——显式声明能提升构建性能。

新特性:Temporal API类型支持

等了好几年的Temporal API,TypeScript终于内置类型了。配置"lib": ["esnext"]"target": "esnext"即可使用:

let yesterday = Temporal.Now.instant().subtract({ hours: 24 });let tomorrow = Temporal.Now.instant().add({ hours: 24 });console.log(`Yesterday: ${yesterday}`);console.log(`Tomorrow: ${tomorrow}`);

编译通过,类型推导完整。Temporal比Date好用太多了——不可变、时区感知、API清晰。不过要注意:类型支持归类型支持,运行时还得看你的Node.js版本或浏览器是否已经实现了Temporal。目前Deno和部分新版浏览器已经支持。

新特性:Map.getOrInsert

ECMAScript的upsert提案到stage 4了,TypeScript 6.0直接加了类型支持:

const cache = new Map<string, number[]>();// 以前的写法if (!cache.has("key")) {  cache.set("key", []);}const items = cache.get("key")!;items.push(42);// 现在一行搞定const items2 = cache.getOrInsert("key", []);items2.push(42);

还有个getOrInsertComputed,适合默认值计算开销大的场景:

someMap.getOrInsertComputed("key", () => {  return computeExpensiveValue();});

这个API简单实用,少写了一堆样板代码。

新特性:RegExp.escape

终于不用自己写正则转义函数了:

const userInput = "hello (world) [test]";const escaped = RegExp.escape(userInput);// escaped: "hello \\(world\\) \\[test\\]"const regex = new RegExp(`\\b${escaped}\\b`, "g");

配合es2025 target使用。

方法语法推断修复

这个修复虽然小但很实用。以前用method syntax写对象字面量里的函数,属性顺序会影响类型推断:

declare function callIt<T>(obj: {  produce: (x: number) => T,  consume: (y: T) => void,}): void;// 箭头函数 - 没问题callIt({  consume: y => y.toFixed(),  produce: (x: number) => x * 2,});// 方法语法 - 以前会报错!y推断为unknowncallIt({  consume(y) { return y.toFixed(); },  produce(x: number) { return x * 2; },});

6.0修复了这个问题。原因是方法语法有隐式的this参数,TS以前把它当成”上下文敏感”的函数,推断优先级低。现在如果函数里没用到this,就不算上下文敏感了。

为TypeScript 7.0做准备:–stableTypeOrdering

这个flag是专门为6.0到7.0迁移准备的。背景是TypeScript 7.0用Go重写后会做并行类型检查,但并行意味着类型的内部ID分配顺序不确定了。为了保证输出一致性,7.0改用了基于内容的确定性排序算法。这会导致union类型的显示顺序和6.0不同。举个例子:

export function foo(condition: boolean) {  return condition ? 100 : 500;}// 6.0可能输出: 100 | 500// 7.0会输出: 100 | 500(确定性排序)

看起来一样?加个看似无关的变量就不一样了:

const x = 500;export function foo(condition: boolean) {  return condition ? 100 : 500;}// 6.0输出: 500 | 100(因为500的typeID先分配)// 7.0输出: 100 | 500(确定性,不受声明顺序影响)

开启--stableTypeOrdering可以让6.0的排序行为对齐7.0。但官方说了这flag会让类型检查慢25%左右,所以只在迁移对比时用。

Subpath Imports支持 #/ 前缀

Node.js的subpath imports以前不支持#/开头,只能写#root/xxx这种。现在Node.js支持了,TypeScript 6.0跟进了:

{  "name": "my-package",  "type": "module",  "imports": {    "#": "./dist/index.js",    "#/*": "./dist/*"  }}
import * as utils from "#/utils.js";

终于可以用#/代替@/了,而且这是Node.js原生支持的,不需要bundler。在moduleResolution设置为node20nodenextbundler时可用。

dom.iterable不用单独引入了

以前要遍历DOM集合,tsconfig的lib要同时写domdom.iterable

// 以前需要 "lib": ["dom", "dom.iterable"]for (const el of document.querySelectorAll("div")) {  console.log(el.textContent);}

现在dom.iterabledom.asynciterable已经合进dom了,写"lib": ["dom"]就够了。不大的改动,但少了一个经常忘记的配置项。

升级建议

如果你打算从5.x升级到6.0,需要注意的事情不少。官方出了个ts5to6迁移工具,可以自动调整baseUrl和rootDir。我建议的升级步骤:

  1. 先装beta跑一下tsc --noEmit,看有多少错误
  2. 处理默认值变化:加上显式的rootDir、types、module配置
  3. 如果错误太多,先加"ignoreDeprecations": "6.0"临时过渡,但7.0不会支持这个选项
  4. --stableTypeOrdering跑一次,提前发现7.0会遇到的类型排序差异
  5. 逐步修复类型错误,大部分是加显式类型注解就能解决

该不该现在升级

Beta阶段不建议生产项目直接上。但强烈建议现在就拉个分支试一下,因为6.0的breaking changes不少,越早知道自己的项目受多大影响越好。这个版本真正让我期待的其实是TypeScript 7.0。Go重写+并行类型检查,大型项目的编译速度应该会有质的飞跃。6.0就是在给那个未来铺路。