Deprecate `--target es5`, make lowest target `es2015`
Overview
With TypeScript 7.0, we have no plans to port over our downleveling from ES2015/ES6 to ES5. ECMAScript 5 was a stable and broad target that seemed like the safest option years ago, but the need to support ES5 environments has shrunk dramatically. Additionally, there is quite a bit of complexity in supporting the transformation of generators.
ES2015 is 10 years old at this point, and is a reasonable lowest target.
Because TypeScript 7.0 will not support --target es5, TypeScript 6.0 will be deprecating it.
That means that TypeScript 6.0 will allow you to use --target es5, but you will receive an error that can only be silenced via ignoreDeprecations.
Users who do rely on ES5 runtimes will be able to use older versions of TypeScript for its downlevel compilation capabilities, Babel, or another compiler. But we do encourage teams to re-evaluate whether they need to support ES5 runtimes.
lib, lib.d.ts, and the DOM libraries
Today, lib.d.ts (TypeScript's nickname for its family of built-in library files) is broken up into many files like lib.es5.d.ts, etc.
Changing the default minimum target means that we need to reconsider what default library files get included based on the target, and how lib continues to function. One complication here is the interplay between whether dom includes dom.iterable, or vice versa.
Most recently, our thinking here is:
es5continues to exist as alibtarget so that it is not an error to reference- the
es2015liboptions automatically includeses5 - the contents of
dom.iterableeffectively gets included as part of usingdom dom.iterablewill become empty so that it is not an error to reference
Some experimentation around this is taking place at https://github.com/microsoft/TypeScript/pull/62025
--downlevelIteration
--downlevelIteration controls whether or not the JS "iterator protocol" is respected (i.e. using Symbol.iterator and the like) by constructs like array spreads, for/of loops, etc. Otherwise, TypeScript would downlevel these constructs in a naive way (e.g. concat and for loops with counter variables).
But this functionality is just assumed to work in ECMAScript 2015, and the flag does nothing in --target es2015. We may want to issue an error message if this flag is specified in conjunction with any newer target, but it seems unnecessary to do so.
See more deprecation discussions at https://github.com/microsoft/TypeScript/issues/54500.
An aspect of this is that dom.iterable being moved into dom is that dom will reference lib.es2015.d.ts, and therefore our default lib (which includes DOM) will also be raised. Which, I think we already also want. But it also means that we are explicitly giving up the ability to check DOM with just es5, which, fine.
True legacy environments (ES5) are vanishingly rare
Hello, I'd just like to give a different perspective on this. In the world today there are still many devices that only support ES5. For example:
- 117 million PS4s, based on Chromium v44
- 350 million smart TVs pre-2018, with Samsung based on Chromium <v47 and LG based on Chromium <v38
- Millions of set-top boxes that vary by country and ISP
We at PeacockTV, SkyShowtime and NOW care deeply about supporting this older hardware, even if it was released more than 10 years ago, because it's what our users own.
Admittedly this is probably niche — I don't know if there are many companies or devs developing apps for TVs and consoles. But for those of us who are "stuck in the past", taking away --target es5 will necessarily require us to stay on TypeScript 6.0 and forego all the goodies and improvements of TypeScript 7.0 (which we are very much looking forward to).
Why can't you run your output through babel to lower to ES5?
Might as well ask why you can't just use an older version of typescript.
You can. Either way, it's just a more complicated, less pleasant solution. I don't expect ES5 support to be kept. There's a cost to it. But there is a non-zero upside to it as well.
The statement being responded to there was "we'll have to forego all the goodies and improvements of TypeScript 7.0", which implies an inability to use an alternative downleveler.
Call me charitable, I guess. To me it's an imperfectly conveyed sentiment that TypeScript 7 (alone, as-is) will not be suitable for their needs, not that someone doesn't know what babel is or else refuses to consider it. I hope we can all agree that (1) yes, Babel exists and (2) that nonetheless the value of es5 support is non-zero but understandably small.
Probably! But if there's an actual technical blocker that we hadn't thought of, we would want to know about it.
which implies an inability to use an alternative downleveler.
That's assuming too much. It implies a desire to not use an alternative downleveler. We were eager to try the new speeds advertised at the start of the year. "A 10x Faster TypeScript", it said. Except if you're transpiling to ES5, I suppose.
With this deprecation going forward we'll certainly need to investigate alternatives to tsgo, particularly esbuild and swc. We'd rather avoid babel as it's quite slow for our needs. I should note that with the official TypeScript tool deprecating transpilation to ES5, I wouldn't be surprised if these other tools decide to do the same. They have less resources than Microsoft and obviously there's a cost to supporting ES5.
I do think we should be careful with statements like:
Virtually every runtime environment is now "evergreen". True legacy environments (ES5) are vanishingly rare
That's why I tried to back my previous comment with some data and show the perspective of those companies and devs that still transpile ES5 to support their users. You'd be surprised by the TVs our parents and grandparents use. Not to mention developing countries where millions still use Opera Mini.
True legacy environments (ES5) are vanishingly rare
Hello, I'd just like to give a different perspective on this. In the world today there are still many devices that only support ES5. For example:
- 117 million PS4s, based on Chromium v44
- 350 million smart TVs pre-2018, with Samsung based on Chromium <v47 and LG based on Chromium <v38
- Millions of set-top boxes that vary by country and ISP
We at PeacockTV, SkyShowtime and NOW care deeply about supporting this older hardware, even if it was released more than 10 years ago, because it's what our users own.
Admittedly this is probably niche — I don't know if there are many companies or devs developing apps for TVs and consoles. But for those of us who are "stuck in the past", taking away
--target es5will necessarily require us to stay on TypeScript 6.0 and forego all the goodies and improvements of TypeScript 7.0 (which we are very much looking forward to).
It absolutely is not niche. I would like to add our boost to this as we support all of those boxes and MANY more in international countries.
It absolutely is not niche. I would like to add our boost to this as we support all of those boxes and MANY more in international countries.
I'd be surprised if the amount of projects using "target": "es5" reaches anything close to 10%. A vast majority of projects likely also require a build/packaging step that can updated to transform code to ES5, so not keeping support in TS seems very reasonable IMO.
There's many options to chose from if you still need to support ES5:
- If using a bundler, use the
targetconfig for the tool used (Vite, Rolldown, esbuild, etc) - For plain
tsc, just add a step aftertscto down-level, e.g. usingswc"scripts": { "build:ts": "tsc -p tsconfig.json", "build:es5": "swc dist/esm -d dist/es5", "build": "npm run build:ts && npm run build:es5" } - Keep using TypeScript v6.0.0
Personally, I think it's better if TypeScript focuses on checking that code is valid, and leave down-leveling to different platforms to a bundler.
Personally, I think it's better if TypeScript focuses on checking that code is valid, and leave down-leveling to different platforms to a bundler.
By that line of reasoning, why deprecate only ES5? Why not deprecate ES6? ES2016? Is the long term vision for tsgo that it should only strip away types?
I'd be surprised if the amount of projects using
"target": "es5"reaches anything close to 10%
Seems like a wild guess. It'd be very interesting to have that data, actually.
A quick search on GitHub yields this:
| Version | number files |
|---|---|
| ES5 | 459k |
| ES6 | 276k |
| ES2018 | 102k |
| ES2022 | 384k |
| ESNEXT | 434k |
My query most likely has flaws. If you can, please critique it / improve it. I'll be honest, I'm not sure if this is really indicative of any real world numbers. But perhaps usage of ES5 isn't as low as we believe it to be.
A better query would look like this: https://github.com/search?q=%2F%22target%22%5Cs*%3A%5Cs*%22es5%22%2F+language%3Ajson&type=code
Which has 15k of ES5, 37.6k of ES6/ES2015, 27.5k esnext, etc.
By that line of reasoning, why deprecate only ES5? Why not deprecate ES6? ES2016? Is the long term vision for tsgo that it should only strip away types?
The ES5 target in particular is very complex to maintain, due to async/await state machine plus 100% class downleveling. Most transforms apart from decorators are relatively quite cheap (and decorators do not have any extant runtime support, thus not a feasible cut target).
But perhaps usage of ES5 isn't as low as we believe it to be.
The usage number is a bit of a slippery thing. A project that has target: es5 might be simply unmaintained, might have set that a dozen years ago and never looked at it again, might have copied it from somewhere else without thinking about it, etc..
Our telemetry of project configs (via editors) shows that the most common configs are esnext, es2022, es2020, and es2017. ES5 represents about 8% of sessions. But if you go out and look at projects that set target: es5, most of them don't make any sense -- for example, this VS Code extension sets target: es5, but Electron's very first version was ES6, and in 2019 when this extension was written, it had ES2017 support. We're definitely not saying there are no ES5 projects out there, just that the few that are a) big enough / active enough to really need 7.0 in the first place and b) not already using a non-tsc JS emit pipeline are rare enough to justify the improved engineering throughput on our side.
By that line of reasoning, why deprecate only
ES5? Why not deprecateES6?ES2016? Is the long term vision fortsgothat it should only strip away types?
I'm not on the TS team, so I wouldn't know the long term plans. But it's reasonable to assume that they are trying to limit the amount of breaking changes, since many bigger enterprise projects use tsc directly (with "composite" references).
It seems more common for new/maintained projects seem to gravitate towards "isolatedModules": true, where NodeJS/Vite/tsup/etc can transpile TypeScript without running tsc. TypeScript is often run as check next to linting via tsc --noEmit, while bundlers handles downleveling code instead after stripping types.
Not saying this is the direction things will go, but it's a possibility.
The usage number is a bit of a slippery thing. A project that has target: es5 might be simply unmaintained, ...
I was about to mention this too. I didn't see a way to make a GitHub query for projects with recent commits though. 😅
The ES5 target in particular is very complex to maintain
@RyanCavanaugh That argument I can understand. The reason I questioned the long term vision for tsgo was because you 👍'ed a comment that said:
I think it's better if TypeScript focuses on checking that code is valid, and leave down-leveling to different platforms to a bundler.
To me, this kind of argument seems disingenuous. I'd hope this not to be TS's long term vision.
As for the cost of maintaining ES5, well, yes, that is an understandable argument.
@jakebailey I think that query is worse than the one I provided. There are 12 million repositories with TypeScript, so those numbers seem way too low.
Now, what @RyanCavanaugh pointed is true. Some of the repositories found in the wild may no longer be maintained. But that kind of argument applies to all repositories, not just the ones that use ES5. And the only reason I used this data was because it was the only data I had access to.
Our telemetry of project configs (via editors) shows that the most common configs are esnext, es2022, es2020, and es2017. ES5 represents about 8% of sessions.
Now this is very interesting. How did you calculate those 8%? Was it by looking at the target set in tsconfig.json files? Because, for example, this is how our base tsconfig.json looks like in our various projects:
"target": "es2018",
"lib": ["webworker", "DOM", "ES2022"],
And yet we transpile to ES5. We want our editor to not scream at us but allow a more modern syntax, which we then downlevel when necessary. I'd imagine other teams have a similar approach.
So I'd say that that telemetry only proves that the floor for ES5 is 8% of sessions. And 8% of sessions already seems like a significant number.