Comparison

TypeScript 5.9 vs 6.0 vs 7.0 for JavaScript projects

What changes for checked JavaScript across TypeScript 5.9, 6.0 and the 7.0 native port: defaults, removed options, JSDoc 7.0 drops, speed, and an upgrade path.

  • Examples checked with TypeScript 5.9

At a glance

Last verified 21 October 2026 with TypeScript 5.9.3; the 6.0 and 7.0 results come from one run each of 6.0.3 and 7.0.2 over this site's 484 example projects on 20 October 2026.

Compared TypeScript 5.9TypeScript 6.0TypeScript 7.0
Released 1 August 202523 March 20268 July 2026
Written in TypeScript, run on Node.jsTypeScript, run on Node.js (the last such release)Go: a native tsc
strict by default OffOnOn
types by default Every @types package[]: none unless listed[]
module and target by default commonjs and es5esnext and the newest ECMAScript yearAs 6.0
baseUrl, moduleResolution: node, target: es5 AcceptedDeprecated (TS5101, TS5107)Removed (TS5102, TS5108)
@enum, @class functions, Closure function types, a value as a type ReadReadNot read
This site's 484 example projects The baseline474 identical, 10 differ (defaults and deprecations)460 identical, 24 differ (10 defaults, 14 JavaScript changes)
Speed, per the 7.0 announcement Not comparedThe baselineFull builds 8 to 12 times faster than 6.0
Programmatic API (for linters and other tools) YesYes, as in 5.9None yet; 7.1 is meant to bring one

Three releases, one direction

TypeScript 5.9 is the version this site checks every example with. 6.0 is the last release written in TypeScript: it changes several defaults and deprecates old options, and otherwise behaves like 5.9. 7.0 is the native port, rewritten in Go and run as the same tsc from the same typescript package; it keeps 6.0’s defaults, removes what 6.0 deprecated, and reads JavaScript files more like TypeScript files. The release pages cover each in detail: 5.9, 6.0, 7.0.

What the one-off runs showed

On 20 October 2026 we ran TypeScript 6.0.3 and 7.0.2 over the 484 example projects this site checked at the time, and compared each project’s errors with what 5.9.3 reports:

  • 6.0.3: 474 projects reported exactly the same errors. The 10 that differed each set, or left out, an option whose default changed or that 6.0 deprecates.
  • 7.0.2: 460 identical. Of the 24 that differed, 10 differ for the same reasons as under 6.0, and 14 because of 7.0’s JavaScript changes: @enum, @class and @constructor functions, Closure function types, a value used as a type, arguments no longer allowing extra arguments, @private in a constructor function, and three errors reported with a different code or not at all.

Those were one-off runs in a scratch folder, not part of this site’s build; the examples added since then have not been run under 6.0 or 7.0.

What 7.0 stops reading

Four JSDoc patterns are behind most of the differences. Each has a replacement that passes in 5.9, 6.0 and 7.0 alike, so the rewrite can happen before the upgrade.

@enum

@enum is an ordinary tag in 7.0. This example passes in 5.9 and, in our run, failed under 7.0.2 with TS2749:

status.js TypeScript 5.9.3 · checked 21 October 2026
/** @enum {string} */
export const Status = {
  Draft: "draft",
  Live: "live",
  Archived: "archived",
};

/**
 * @param {Status} status
 * @returns {boolean}
 */
export function isVisible(status) {
  return status === Status.Live;
}

isVisible(Status.Draft);
An object of constants with @enum.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

The replacement is a const object and a union of its values, which also checks the values more tightly in every version:

status.js status.ts Error confirmed · TypeScript 5.9.3 · checked 21 October 2026
export const Status = /** @type {const} */ ({
  Draft: "draft",
  Live: "live",
});

/** @typedef {(typeof Status)[keyof typeof Status]} StatusValue */

/** @param {StatusValue} status */
export function setStatus(status) {
  return status;
}

setStatus(Status.Live);
setStatus("deleted");error TS2345: Argument of type '"deleted"' is not assignable to parameter of type 'StatusValue'.
export const Status = {
  Draft: "draft",
  Live: "live",
} as const;

type StatusValue = (typeof Status)[keyof typeof Status];

export function setStatus(status: StatusValue) {
  return status;
}

setStatus(Status.Live);
setStatus("deleted");error TS2345: Argument of type '"deleted"' is not assignable to parameter of type 'StatusValue'.
For a closed set of values, use a const object and a union.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Closure function types

7.0 does not parse {function(string): number} (TS1005 in our run). Arrow syntax works everywhere:

sort.js sort.ts TypeScript 5.9.3 · checked 21 October 2026
/** @typedef {{ sku: string, price: number }} Product */

/** @type {(amount: number, currency?: string) => string} */
export const formatPrice = (amount, currency = "USD") =>
  new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);

/**
 * @param {Product[]} products
 * @param {(a: Product, b: Product) => number} compare
 */
export function sorted(products, compare) {
  return [...products].sort(compare);
}

sorted([{ sku: "TEE-01", price: 19.5 }], (a, b) => a.price - b.price);
formatPrice(19.5);
type Product = { sku: string; price: number };

export const formatPrice: (amount: number, currency?: string) => string = (amount, currency = "USD") =>
  new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);

export function sorted(products: Product[], compare: (a: Product, b: Product) => number) {
  return [...products].sort(compare);
}

sorted([{ sku: "TEE-01", price: 19.5 }], (a, b) => a.price - b.price);
formatPrice(19.5);
Function types in arrow syntax.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Constructor functions

Functions marked with @class or @constructor are no longer read as classes (TS2683 and TS7009 in our run). Write a class; the @class page shows both.

A value’s name as a type

{defaults} meaning typeof defaults is TS2749 under 7.0. Write typeof, as the ReturnType page does.

Speed

The 7.0 announcement reports full builds 8 to 12 times faster than 6.0, through native code and checking files in parallel (the experimental --checkers option sets how many type-checking threads run). We did not benchmark it; the figure is the announcement’s. For a JavaScript project the gain shows up as a faster npm run lint and quicker errors in the editor.

The tools question

7.0 ships without a programmatic API, which 7.1 is meant to bring. Tools that call TypeScript as a library, typescript-eslint among them, and editor support for Vue, Svelte, Astro and MDX files, still need 6.0, which the TypeScript team publishes as @typescript/typescript6 (with a tsc6 command) so that both can be installed. This site’s own examples gate is one such tool, which is why it still runs 5.9.

An upgrade path

  1. Write down your defaults on 5.9. Set strict, types, module and target explicitly in jsconfig.json, so the defaults that matter most do not move under you; the 6.0 page lists every default that changes.
  2. Move to 6.0 and fix every deprecation error, rather than silencing them with "ignoreDeprecations": "6.0": the common ones in JavaScript projects are baseUrl and moduleResolution: "node".
  3. Turn on stableTypeOrdering in 6.0 to see 7.0’s type ordering, which matters most if you publish .d.ts files written from JSDoc.
  4. Rewrite the four JSDoc patterns above. The replacements pass in 5.9 and 6.0 already, so this can happen before any upgrade.
  5. Try 7.0 beside 6.0 with npx -p typescript@7 tsc -p jsconfig.json, and switch when it reports what 6.0 reports. Keep 6.0 installed for tools that need its API.

Which to choose

Choose TypeScript 5.9 when…

  • Your tools call TypeScript as a library and have not moved on, and you are not ready to set the 6.0 defaults explicitly.
  • You want the version this site's examples are checked with today.

Choose TypeScript 6.0 when…

  • You are on the way to 7.0: it reports every option 7.0 removes, while still running your tools.
  • You need the old JSDoc forms (@enum, constructor functions) for a while longer, with the new defaults.

Choose TypeScript 7.0 when…

  • Checking time matters: a large codebase, an editor that lags, a slow CI step.
  • Your JSDoc already uses the forms 7.0 reads (typeof, union @typedefs, class, arrow function types), and no tool you rely on needs the API.

Questions

Do I have to rewrite my JSDoc for TypeScript 7.0?

Only the older forms: @enum, @class constructor functions, Closure function types such as function(string): number, and a value's name used as a type. Each has a replacement that already works in 5.9, so you can rewrite before upgrading.

Does a jsconfig.json still work in 6.0 and 7.0?

Yes. In our one-off runs, a jsconfig.json kept its file-name defaults under both. It also got the new defaults (strict on, types: []), so a config that relied on the old ones reported errors 5.9 did not. Setting strict and types explicitly avoids that.

Why does this site still check with 5.9?

The examples gate uses TypeScript's programmatic API, which 7.0 does not have yet. Moving the pin is planned; until then, pages note where 6.0 or 7.0 behaves differently, based on the release notes and the one-off runs.

Sources

Last reviewed 21 October 2026.