-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
TypeScript Version: 3.9.7, 4.0.0-dev.20200725
Search Terms:
template literals, template strings, ES5, ES3
Code
class C {
toString() {
return "toString()";
}
valueOf() {
return "valueOf()";
}
}
const c = new C;
const s = `${c}`;
console.log(s);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 by valueOf() (unless there is [Symbol.toPrimitive](), but I'll just ignore it here as Symbols 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 calling valueOf() and then by toString(), which is the opposite of the expected behavior.
"use strict";
var C = /** @class */ (function () {
function C() {
}
C.prototype.toString = function () {
return "toString()";
};
C.prototype.valueOf = function () {
return "valueOf()";
};
return C;
}());
var c = new C;
var s = "" + c;
console.log(s);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)