For various reasons that are discussed in other issues, some people like to pipe TS into Babel for the downlevel (e.g. ES5) code generation. I won't reiterate here why one might want to do so.
Now that TS is starting to get ES7+ features such as async
, decorators, possibly ::
& co. it would be very welcome to add a ES7 (ES2016) target.
The use case today is to get raw, non transformed code from TS and process it with Babel.
The future use case is of course that JS runtimes are going to have some of those features natively supported and down-level emit won't be required anymore.
I still think this is challenging and that a simple "es6/es2015" or "es7/es2016" target won't solve the challenges... It almost needs some sort of granular feature flag. I am not familiar with it, but how is Babel handling these sort of control of these emits?
Also, is it a fair assumption at this point that an ES6+ feature ever be down emitted in ES6 as well as ES5/ES6? For something like exponation, the emit wouldn't change, but in theory if there was a down-emit for async to ES6, you could emit Promises but you couldn't do that to ES5.
@kitsonk OK, I'm going on a tangent with respect to this ticket.
The business of emiting JS for down-level browsers is a complex thing, which is mostly unrelated to the TypeScript language. On several aspects, Babel does a better job than TS at this. That's why some people pipe TS (for static typing) into Babel (for ES5 emit).
Granularity is one example of this. Babel supports enabling/disabling any Transformer individually. That's why it is enough that TS passes through ES7 code, I can handle the granular transpiling with Babel.
I don't mind TS supporting more emitting options (I think granularity is #4692), but letting the ES7 code passthrough is an easy step that supports such a workflow right now.
Also, is it a fair assumption at this point that an ES6+ feature ever be down emitted in ES6 as well as ES5/ES6? For something like exponation, the emit wouldn't change, but in theory if there was a down-emit for async to ES6, you could emit Promises but you couldn't do that to ES5.
Not sure I got the point here.
A real world use case for this would be the next major release of Koa.js which will natively support async/await in addition to the current generator syntax. While it works nicely with async functions transpiled by Babel it does not play well with the async functions transpiled by typescript (although I guess maybe that could be addressed separately).
It also seems cleaner to me to have typescript deal with all the static analysis stuff but have a specialised tool like Babel handle the transpiling from ESn to ESm
Not sure I got the point here.
There are likely to be features introduce in ES7 and beyond that would be better to emit as ES6 when possible. For example you could use WeakMaps/Promises/Symbols to better polyfill functionality in ES6 which is likely more performant (and less likely to have unintended consequences). Even using let
and const
in the down emit can make code behave better (and be less likely to leak/interfere with other code). Let's say decorators... maybe the environment doesn't support decorators (ES7) but supports classes (ES6). Why down emit everything to ES5?
Again, I don't see anyway of properly supporting it without some sort of micro-targeting. ES7/ES2016 will be a moving target for a long time.
@kitsonk I may be misunderstanding you but I think Babel allows you to do exactly that. It gives you fairly granular control over what transforms and polyfills you use to emit code, so for example when targeting node >= 0.12 I can turn off the regenerator transform to take advantage of native generator support.
If there were a way to leave all es7 features untouched in the output, in exactly the same way as the es6 target leaves all es6 features untouched, then a downstream transpiler such as babel could be used to selectively transform code or not as the platform requires.
@kitsonk exactly what @robotlovesyou said.
In babel each feature is handle by a specific _transformer_, and each one can be enabled/disabled as you want. So to quote your example, I could have "native" ES6 classes and transpile the decorators.
Anyway, in the long run as browsers evolve we will not transpile code anymore so a ES2016 target is required, juste like an ES6 target was added back then.
Another added benefit is that it enables TS team to add new features without downlevel support first (or ever... let
in loop captures?). They did that for several features in the recent releases and I love it because it means sooner availability of async, etc. And we can still downlevel emit with Babel...
While it works nicely with async functions transpiled by Babel it does not play well with the async functions transpiled by typescript
@robotlovesyou can you elaborate on the issue here? can we file another issue with more details? if it is not working we would love to know why and what can be done to fix it.
We have discussed adding a --target ESNext
or something along these lines. the problem is ES7/ES2016 is not finalized yet. proposals that reach stage 3 are likely to be in, but it is not clear about the other ones. for instance it is not clear that decorators will be in ES2016.
@mhegazy I think TS is evolving along with ES specs.
You support ES2016 proposals so I think it makes sense to have a ES2016 target.
If a feature slips out of ES2016 -- e.g. Decorators -- I suggest you update the TS compiler to polyfill them in ES2016 and let them through in the ES2017 target.
Indeed for people that want to always be on the bleeding edge, an ESNext
target that transpiles nothing at all is interesting. Especially for scenarios like Babel.
I may be misunderstanding you but I think Babel allows you to do exactly that.
I thought we were talking about TypeScript. The proposal was to add a new target to TypeScript. I am suggesting that @jods4 proposal over simplifies that problem and that something more is needed and that has additional considerations.
If a feature slips out of ES2016 -- e.g. Decorators -- I suggest you update the TS compiler to polyfill them in ES2016 and let them through in the ES2017 target.
The challenge with that is one day you compile and you get passed through code, and the next day you get down emitted. :frowning:
I am suggesting that @jods4 proposal over simplifies that problem
I think the point is that there are different "problems" at hand, and this issue is not meant to solve your "problem".
_My_ problem is that I want to be able to get JS code without any transpiling at all.
_Your_ problem seems to be that you want more granularity for individual transpiling features.
They are not the same.
Today TS works with standards-based targets: ES3, ES5, ES6. Now that we start adding ES7 features we should add a matching target. It is the natural continuity of existing TS and makes perfect sense.
I don't mind introducing more flexibility, but that's a different discussion.
The challenge with that is one day you compile and you get passed through code, and the next day you get down emitted.
Is it a challenge? If you say "I want to target ES7 compliant browsers" and decorators are not in the standard anymore, then it's as it should be. Given that ES7 is not finalized yet if you ask for such a target you should be ready for that. And "down emitted" code would actually still works.
If you want stability target something stable, like ES5 or ES6.
If you want the bleeding edge, I think we need a new ESnext
target or something like that, although that was not the initial point of this issue.
If you say "I want to target ES7 compliant browsers"
I think that is the root of the problem... We are likely to be in a constant evolving situation, where browsers will likely ever be in a static situation where you can specifically target that browser. Kangax's compatibility tables demonstrate this clearly. The agreed standards are already a moving target and then the standards that aren't even close to being finalised. There will never be something as an "ES7 compliant browser". Likely TC39 will cut ES7 as whatever is agreed at a particular point in time and everything else gets rolled forward. Like Object.observe
was part of ES6, then moved to ES7 and may or may not make that, though V8 already has it implemented.
There will never be something as an "ES7 compliant browser".
Actually, most likely there will.
It is my understanding that Edge was planned to be ES6-compliant this year and that FF and Chrome are working hard to follow suite as soon as possible.
That's great news and it means we won't need polyfills for all this stuff in 2016 (if you can target the latest browsers only, of course). Something similar will happen for ES7,you just need to wait a little longer.
Given the new TC39 yearly schedule, ES7 is ES2016 and it will be frozen next year. Give it one (or two?) years and you'll see ES2016 compliant browsers.
And then we'll need a ES2017 target next year.
+1
I am definitely for this proposal. I already pipeline typescript and babel but would like the option of just letting typescript handle types, and do the es7 to es5 transpilation in one step.
+1
I was about to open the same issue and found this. At present there is no combination of compiler switches that allows ES7 async/await
to just pass through - it is unconditionally down-levelled. I'd like the option to have it pass through as-is to the rest of my build pipeline.
TS 1.8 breaks bluebird usage (https://github.com/Microsoft/TypeScript/pull/6631#issue-128969145). So, I don't want to let TS transform async/await anymore — I want to use babel (http://babeljs.io/docs/plugins/transform-async-to-module-method/). So, ES7 target (do not transform async/await) is wanted.
Hi @mhegazy,
Given the final feature set of ES2016 has been agreed I wonder if you might look again at an ES2016 target? In the end it's only these that made the cut:
I think you've already go the Exponentiation supported?
Adding the ES2016 target should be a simple task. but i wounder if it will be of any value. most comments on this thread really wanted --target ESNext
Personally, I think the ES2016 feature set is so minimal it's barely worth the effort. TypeScript already supports the exponent operator, and includes
is just a .d.ts
change if you're using a polyfill library.
ESNext would be a good target to have, but what would it allow? Assuming async + await would end up there? Decorators? Bind operator?
ESNext would be a good target to have, but what would it allow? Assuming async + await would end up there? Decorators? Bind operator?
that is what we need to define. possibly anything that has a standards proposal even a stage 0 one.
@jamiewinder @mhegazy I think what people who ask for --target ESnext
want is basically a "passthrough". TS compiler removes what is TS-specific (i.e. type annotations, enums, etc.) and leaves everything else untouched. Main idea is to use another transpiler, more often than not, Babel.
Writing that out loud makes me wonder: maybe someone (could be community) could write a Babel plugin that removes the TS syntax?
That way one could run TS with --noEmit
to verify source is correct, and then run Babel to compile it down to whatever target one wants.
Doing so would lessen the need for --target ESnext
.
EDIT just realized it's not as easy as it may seem. Syntax can't be cleaned up without performing some semantic analysis. For instance you need to remove the interfaces... including in other modules where they might be imported. So it's not trivial.
I figured you were going to add es2016 at some point. I just wondered if now would be sensible given the state of things. Perhaps I should have raised this separately. I'm using Babel for transpilation, I thought switching to the es2016 preset would be the smoothest upgrade if TypeScript supported that target also.
@jods4 take a look at this: https://github.com/Microsoft/TypeScriptSamples/tree/master/es6-babel-react-flux-karma
The point is you write es2015 TypeScript and Babel transpires it down to esOld. As a workflow it rocks.
Yes, TS doesn't support granular target control and so we have to use babel. @johnnyreilly To keep away from gulp and use simple workflow (use only tsconfig and npm scripts), I have written ts-babel.
I should note that granular transformation support is already tracked in https://github.com/Microsoft/TypeScript/issues/4692
@johnnyreilly I do this and I'm happy :smile:
But it has limitations that annoy some people. For instance, currently TS _always_ emits ES6 code for async
. You can't have TS passthrough ES2016(+) and use Babel to transpile your async
code.
I personnally don't care but now that TS adheres to the current specifications of not using custom Promise
implementations, some people would prefer to transpile async
with Babel. And hence they would like a ES2017
/ ESnext
target.
I did not know granular targeting was on the roadmap. Awesome!
+1
Is there any way for async/await not to be transpiled already today?
Is there any way for async/await not to be transpiled already today?
no
Because the original issue is for an ES2016 target, I'm going to say an ESNext target should be discussed separately.
👍 , TypeScript is basically unusable in my current Ember.js stack (which uses Babel) if I can't turn off async/await transpilation.
+1 for a target of "esnext" (or maybe just "edge"), which just remove the typescript specific things (types/enums/namespaces/etc..)
For those of you who use Babel, I have written a Babel plugin native-async-for-typescript, which _reverts_ the TypeScript async/await transpilation back to your original async
function.
Another reason for adding ES7/ES8 transpile "support" in TypeScript is that it could enable es2016.d.ts and es2017.d.ts automatically.
What's the best practice on including these definitions files at the moment?
EDIT: Solved this by updating to TypeScript 2.x and adding the following to compilerOptions
in tsconfig.json:
"lib": ["es2017", "dom"]
The original request should be handled by https://github.com/Microsoft/TypeScript/pull/11407. --target ES2016
and --target ES2017
should be supported now.
https://github.com/Microsoft/TypeScript/pull/12160/commits/7b9a42f9958b072f057d42d506b7e082ebf19974 adds a new --target esnext
as well to get experimental features passed through.
Most helpful comment
The original request should be handled by https://github.com/Microsoft/TypeScript/pull/11407.
--target ES2016
and--target ES2017
should be supported now.