Skip to content

6.0 Deprecation Candidates #54500

Open
Open
@RyanCavanaugh

Description

@RyanCavanaugh
Member

We're planning the following set of deprecations for TypeScript 6.0. While TypeScript 6.0 will follow the same "soft deprecation" strategy as TypeScript 5.0, these options will be removed entirely in TypeScript 7 (the native TypeScript port).

Please let us know if these would be unreasonably disruptive for you by leaving a comment here.


In the two years since TypeScript 5.0, we've seen ongoing shifts in the JavaScript ecosystem:

  • Virtually every runtime environment is now "evergreen". True legacy environments (ES5) are vanishingly rare
  • Bundlers and ESM are the most common module environments, but CommonJS is still a major target. AMD and other in-browser userland module systems are much rarer than in 2012
  • Almost all packages ship as some form of module. UMD packages still exist, but virtually no new code is only available as a global variable
  • tsconfig.json is nearly universal as a config mechanism
  • Appetite for "stricter" typing continues to grow
  • TypeScript build performance is top of mind. Despite the gains of TypeScript 7, we still must always have performance as a key goal, and options which can't be supported in a performant way need to be more strongly justified

Modernization

Newer Default Values

  • The new default target is es2015
  • The new default module is esnext
  • strict is now true by default

--outFile removed

Removed for implementation simplicity's sake.
External bundlers or transpilers do this job faster, better, and more configurably.

Removed Flag Values

  • module: amd, module: umd, and module: systemjs
  • moduleResolution: classic
  • esModuleInterop: false
  • allowSyntheticDefaultExports: true

This also implies dropped support for the amd-module directive, which will no longer do anything.

Legacy module syntax

Early versions of TypeScript used this construct

module Foo {

}

which was later aliased to the modern preferred form

namespace Foo {

}

module blocks are a potential ECMAScript proposal which would conflict with this syntax, so we're fully deprecating using module where namespace is expected.

The ambient module declaration form

declare module "some-module" {

remains fully supported.

See #61450 for RWC results

DOM tweaks

"lib": ["dom"] will now automatically include dom.iterable as well

Performance

rootDir default

Currently rootDir, if not specified, is inferred based on the set of root files found (unless composite is set).
In 6.0, the default rootDir will always be the directory containing the tsconfig.json file.
If a non-config-based build occurs, rootDir will be inferred as before.

This lets us go faster because we don't need to compute the set of input files in order to determine the structure of the output directory.

types default

Currently, the types value defaults to "enumerate everything in node_modules/@types". This is potentially very expensive as a normal repo setup these days might transitively pull in hundreds of @types packages. Modern projects almost always need only @types/node, @types/jest, or a handful of other common global-affecting packages.

In 6.0, the default types value will be [].
This will affect many projects; you will likely need to add "types": ["node"] or a few others.

This will prevent projects from unintentionally pulling in hundreds or even thousands of unneeded declaration files at build time. Many projects we've looked at have improved their build time anywhere from 20-50% just by setting types appropriately.

Cross-namespace value qualification

In TypeScript today, you can write this code:

namespace Foo {
    export const bar = 10;    
}

// Possibly in another (non-module) file
const bar = "hello";
namespace Foo {
    const x = bar;
}

In this program, the initializer of x actually refers to Foo.bar (value 10), not the outer const bar (value "hello").
Depending on your background, this is somewhere between "expected" and "a huge surprise".
It's also a big implementation problem for us, since it means name resolution of bar in x = bar can't proceed until all files in the program are known.

In TypeScript 6.0, this behavior will be removed, and bar will refer to the outer const (or be a name resolution error if that variable isn't there).

enum merging

It's been possible to merge value enums, but this functionality is very rarely used since it can't cross module boundaries.

See #61262 for RWC run.

alwaysStrict

The alwaysStrict flag refers to inference of the "use strict"; directive. In TypeScript 6.0, all code will be assumed to be in "strict mode", which is a set of JS semantics that mostly affects syntactic corner cases around reserved words.

This lets us be faster because it's no longer necessary to look ahead or repase on constructs like

var x = await

which is legal "sloppy mode" referring to a variable named await. This also reduces the number of flags which possibly prevent sharing of source files between projects with different compiler settings.

See #61888 for RWC run; we found one codebase that used static as a parameter name.

Behavorial Tweaks

no-default-lib directives

No one really understands what this does or uses it correctly.

Specifying commandline files when tsconfig.json exists is an error

Currently if you run tsc foo.ts in a folder where a tsconfig.json exists, the tsconfig file is completely ignored. This is very confusing. The intended meaning of this is also unclear; it could be that you want to use the compilerOptions of the config but not the files and/or include and/or exclude.

For clarity, in 6.0, if you run tsc in a directory with a tsconfig.json, an error will be issued instead.

tsconfig.json is present but will not be loaded if files are specified on the commandline. Use --ignore-config to skip this error

See also #27379

JS Modernization

The asserts keyword was added to the JS language and then removed; in 6.0 this will be a parse error. See also #58453

Conditional imports/exports fallback lookups are deprecated; see #50762
If your name isn't Andrew Branch and you know what this even is about, please let us know.

See also #51000 / #51424 / #51909 / #54500

Activity

added
Meta-IssueAn issue about the team, or the direction of TypeScript
on Jun 2, 2023
RyanCavanaugh

RyanCavanaugh commented on Jun 2, 2023

@RyanCavanaugh
Author
locked and limited conversation to collaborators on Jun 2, 2023
andrewbranch

andrewbranch commented on Jun 2, 2023

@andrewbranch
DanielRosenwasser

DanielRosenwasser commented on Jun 9, 2023

@DanielRosenwasser
RyanCavanaugh

RyanCavanaugh commented on Jan 25, 2024

@RyanCavanaugh
Author
RyanCavanaugh

RyanCavanaugh commented on Mar 1, 2024

@RyanCavanaugh
Author
RyanCavanaugh

RyanCavanaugh commented on Mar 1, 2024

@RyanCavanaugh
Author

24 remaining items

mjames-c

mjames-c commented on Jun 30, 2025

@mjames-c

I have a similar question for removal of esModuleInterop: false -- the docs have this:

true if module is node16, nodenext, or preserve; false otherwise.

in TSv7 will esModuleInterop continue to adhere to this logic or will it always be true regardless of the module type the user selects? I'm also curious if users will always want esModuleInterop: true as it seems to increase the size of compiled code/bundles (although perhaps that's negligible)

JustFly1984

JustFly1984 commented on Jun 30, 2025

@JustFly1984
jakebailey

jakebailey commented on Jun 30, 2025

@jakebailey
andrewbranch

andrewbranch commented on Jul 2, 2025

@andrewbranch
Member

@mjames-c no, the behavior in all modes will be esModuleInterop: true. The behavior has long been the standard way to transpile ESM imports to CommonJS and giving people the option to do something non-standard isn’t helping anyone. The way to escape its impact on emit is to migrate away from compiling to CommonJS.

majames

majames commented on Jul 3, 2025

@majames

@andrewbranch ok cool. what about allowSyntheticDefaultExports?

andrewbranch

andrewbranch commented on Jul 3, 2025

@andrewbranch
Member

The type checking behavior of esModuleInterop: true completely subsumes that of allowSyntheticDefaultExports, so it will also be removed, as toggling it wouldn’t do anything.

jakebailey

jakebailey commented on Jul 9, 2025

@jakebailey
Member

I swear we also mentioned compileOnSave, but I don't see that listed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Meta-IssueAn issue about the team, or the direction of TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @DanielRosenwasser@JustFly1984@andrewbranch@rbuckton@jakebailey

        Issue actions

          6.0 Deprecation Candidates · Issue #54500 · microsoft/TypeScript