-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transpiled template literals behave incorrectly #39744
Comments
Is this something you ran into in a real-world app? |
Yes, I had some trouble when I was trying to interact with Discord API using discord.js. The library defines a class |
As a heads-up, this behaviour will cause problems with the upcoming There's a discussion about TypeScript's transpilation behaviour for template literals at tc39/proposal-temporal#1681 |
This is a spec compliance issue that babel also had to deal with; it’s worth fixing. It also comes up when interpolating Symbols. |
Yep. As a champion of the (currently Stage 3) Temporal proposal, this issue is concerning because it will cause divergence in behavior between spec-compliant interpolation of Temporal instances (which will succeed) and TSC-polyfilled interpolation (which will throw). Given that TS transpilation is sometimes done via babel and sometimes done via TSC, I can see this creating a lot of confusion among developers, esp. those who are less familiar with the bundler/transpilation plumbing that underlies most modern apps. Also, a common use case for interpolation of Temporal instances will be console.log statements, because logs often have timestamps or durations displayed. It'd be a bummer to have logging code that works great in JS suddenly start crashing when porting that code to TypeScript. |
Totally agree. Hopefully typescript, which has a tc39 presence, can match the spec before it becomes a problem. |
@andrewbranch would be great to see this in 4.5 final release if possible. The first (flagged) implementations of Temporal are starting to be released in JS engines, e.g. Safari just shipped the first tech preview with a partial Temporal implementation. And production polyfills are maturing. Would be great to have this fixed in TS before there's too much in-the-wild usage. Thanks! |
We generally avoid breaks after beta periods, so we'd have to investigate this for 4.6. |
Is this a breaking change though? It seems that the current implementation is a bug, and anyone relying on the non-spec-compliant behavior would have an issue if they switched to |
Changing emit is always a risk, but I tend to agree with this being a bug fix, and doesn’t seem like it should be very breaky in practice—it seems like it would be difficult to accidentally take a dependency on the wrong behavior here. |
TypeScript Version: 3.9.7, 4.0.0-dev.20200725
Search Terms:
template literals, template strings, ES5, ES3
Code
Expected behavior:
According to ES2015 (and later) spec, the result of expressions in template literals are converted to primitives first by calling
toString()
and then byvalueOf()
(unless there is[Symbol.toPrimitive]()
, but I'll just ignore it here asSymbol
s wouldn't get transpiled).s
therefore evaluates to"toString()"
.Actual behavior:
s
evaluates to"valueOf()"
.The above code is compiled to the following when the target is ES5 or ES3.
+
operator attempts to convert its operands to primitives first by callingvalueOf()
and then bytoString()
, which is the opposite of the expected behavior.FWIW, Babel compiles the above code to this unless loose transformation is enabled. It makes use of
String.prototype.concat()
and behaves as expected.Playground Link: Link
Related Issues:
#30239: Although OP's suggestion is not related, some people commenting on the issue seem to confront this issue (like this comment)
The text was updated successfully, but these errors were encountered: