Skip to content
Release notesTypeScript

TypeScript 6.0: the bridge release before the Go compiler

TypeScript 6.0 was published on 23 March. A recent create-vue project upgrades with two version bumps, an older one has a baseUrl line to delete, and projects that lint with typescript-eslint should wait for it to catch up.

vuejs.school team24 Mar 20267 min readTypeScript 6.0 · vue-tsc 3.2

TypeScript 6.0 was published to npm on 23 March as version 6.0.2, after a beta on 11 February and a release candidate on 6 March. The announcement calls it a unique release: the last one built on the current JavaScript codebase, and the bridge to TypeScript 7.0, which is being rewritten in Go. Most of what changed exists to get your project ready for 7.0.

For a Vue project, the work is in package.json and the tsconfig files. A project made with a recent create-vue needs two version bumps. An older one also has a baseUrl line to delete, and a hand-written tsconfig.json may need "types": ["node"]. If you lint with typescript-eslint, wait: its latest release does not support TypeScript 6.0 yet.

Why 6.0 is a bridge release

The TypeScript team is porting the compiler and language service to Go, for the speed of native code and for shared-memory multi-threading. That new codebase becomes TypeScript 7.0, while 6.0 stays on the JavaScript one.

The tool 6.0 uses to prepare you is deprecation. Options that 7.0 will not support now raise an error in 6.0. You can silence those errors by adding "ignoreDeprecations": "6.0" to your tsconfig.json, but the announcement is plain that 7.0 will not support any of the deprecated options.

The new defaults

Several options have a new default value. If your tsconfig.json already sets an option, the new default does not affect you. The changes:

  • strict is now true.
  • module defaults to esnext.
  • target defaults to the newest ECMAScript version TypeScript supports, which is es2025 in this release.
  • noUncheckedSideEffectImports is now true. An import with no bindings, such as import './assets/main.css', must resolve to something TypeScript knows about.
  • libReplacement is now false. TypeScript no longer searches node_modules for packages that replace its built-in lib files, a search that cost time on every run and found nothing unless you had set such a package up.
  • rootDir defaults to the folder that contains tsconfig.json, instead of being worked out from your source files.
  • types defaults to [], so TypeScript no longer loads every package in node_modules/@types on its own. The announcement reports builds 20 to 50 percent faster in projects that set types properly.

The last two are the ones the announcement warns about. Many projects will need "types": ["node"], it says, and projects whose output lands in dist/src/ instead of dist/ need "rootDir": "./src".

The deprecated and removed options

These now raise an error unless silenced:

  • target: "es5", since the lowest target is now ES2015, and downlevelIteration, which only affected ES5 output.
  • moduleResolution: "node" (also called node10) and moduleResolution: "classic". Use bundler for code that goes through Vite and nodenext for code that Node runs directly.
  • module set to amd, umd, systemjs or none.
  • baseUrl. Aliases in paths have not needed it for years, and it also made TypeScript resolve bare imports from that folder, which hid imports that would fail at runtime.
  • esModuleInterop: false and allowSyntheticDefaultImports: false. The safer interop is always on now.
  • alwaysStrict: false. All code is treated as JavaScript strict mode.
  • outFile. Concatenating files is a bundler's job.

Two old syntax forms are now errors:

  • module Foo {} for a namespace. Write namespace Foo {}. A declare module '*.vue' block, whose name is in quotes, is not affected.
  • Import assertions written assert { type: 'json' }. Write with { type: 'json' }.

On the command line, running tsc somefile.ts in a folder that has a tsconfig.json is now error TS5112, because the config used to be ignored without a word. Add --ignoreConfig if ignoring it is what you want.

New features you can use

Alongside the deprecations, the release adds:

  • "lib": ["dom"] now contains what dom.iterable and dom.asynciterable held, so for (const li of document.querySelectorAll('li')) type-checks without the extra entries.
  • An es2025 value for target and lib, with types for RegExp.escape. Promise.try, iterator helpers and the new Set methods move from esnext into es2025.
  • Types for Temporal under esnext or esnext.temporal, and for Map.getOrInsert() and getOrInsertComputed() under esnext. These are types only. TypeScript adds no runtime code and Vite adds no polyfills, so check browser support before using them in an app.
  • Subpath imports that start with #/, under moduleResolution bundler and nodenext.
  • --stableTypeOrdering, which makes 6.0 order union types the way 7.0 will. It exists to compare output between the two and can slow type checking by up to 25 percent, so it is not for everyday use.

What a Vue project needs to change

Take a project scaffolded with npm create vue@latest. Its tsconfig.app.json extends @vue/tsconfig/tsconfig.dom.json, which already sets strict, module, target, libReplacement: false and types: []. The tsconfig.node.json and tsconfig.vitest.json files list their types explicitly. Every config sets noEmit, so the rootDir change has nothing to act on. In a recent project the new defaults change nothing, provided env.d.ts is still in place (see below).

Older projects differ in one place. create-vue releases before 3.12.2, published on 29 November 2024, wrote baseUrl into tsconfig.app.json:

tsconfig.app.jsonBreaks
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] }
  }
}

On TypeScript 6.0, vue-tsc --build stops with error TS5101: Option 'baseUrl' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error. The paths entry already starts with ./, so the fix is deleting one line:

tsconfig.app.jsonWorks
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Paths without baseUrl work on 5.9 as well, so you can land this fix before the upgrade.

The second thing to check is env.d.ts. With noUncheckedSideEffectImports on, the CSS import in src/main.ts needs a declaration for *.css files. Vite ships one in its client types, and create-vue loads them in env.d.ts:

env.d.ts
/// <reference types="vite/client" />

If that file is gone, or no longer in include, TypeScript 6.0 reports error TS2882: Cannot find module or type declarations for side-effect import of './assets/main.css'. Put the reference back. A triple-slash reference like this one is not affected by the new types default.

A project with its own hand-written tsconfig.json and no types entry meets the new types default. A file that uses Node's APIs, such as a script that reads process.argv or imports node:fs, now fails with error TS2591: Cannot find name 'process' (or 'node:fs'). The exception is a config that also includes a file importing from vite, usually vite.config.ts: Vite's own type declarations load the Node types, and then every file in that config sees them. A config that covers only src gets no such help. Do not rely on Vite for this; add the Node types to compilerOptions yourself:

tsconfig.json
{
  "compilerOptions": {
    "types": ["node"]
  }
}

How to upgrade

create-vue pins TypeScript with a tilde, "typescript": "~5.9.3", which only allows 5.9 patch releases. npm update will never move you to 6.0, so install it by name. Update @vue/tsconfig in the same command: version 0.9.1, published early on 24 March, widens its peer range to TypeScript 5.8 and later, where 0.9.0 and older ask for TypeScript 5.

npm install -D typescript@~6.0.2 @vue/tsconfig@^0.9.1
npm run type-check

vue-tsc needs no update. Version 3.2.6, published on 17 March, declares any TypeScript from 5.0 up as its peer and runs on 6.0.2 as it is; the TS5101 message above is exactly what it prints.

Most errors after the upgrade come from the new defaults and the deprecations above. The rest come from inference changes. Functions that never use this are now inferred earlier in generic calls, which fixes some errors, and checking of function expressions in generic calls was tightened after the beta, which may add some. If a generic call starts failing, give it an explicit type argument, as the announcement suggests.

Wait if you lint with typescript-eslint

If you picked both TypeScript and ESLint in create-vue, the parser that reads your .ts files comes from typescript-eslint, pulled in by @vue/eslint-config-typescript. Its latest release, 8.57.2, declares support for TypeScript >=4.8.4 <6.0.0.

Install 6.0 next to it anyway and you get two kinds of complaint:

  • From npm, ERESOLVE overriding peer dependency warnings. If you list typescript-eslint directly in package.json, npm stops with ERESOLVE unable to resolve dependency tree instead.
  • From the parser, each time ESLint runs, a banner saying you are running a version of TypeScript that is not officially supported, with a request to file bug reports only on supported versions.

Check with npm view typescript-eslint peerDependencies, and upgrade TypeScript once the typescript range in that output includes 6.0. Until then, you can still delete baseUrl.

If your project does not lint with typescript-eslint, upgrade now: two version bumps, perhaps one deleted line, and a config with no deprecated options left for 7.0 to drop.

Check it stuck3 questions from the Type checking and editor setup quiz.
Practice now
Was this helpful?

Keep reading