For each of these, we may have to consider surrogate pairs.
Currently we do not support spread on strings. The main reason is we do not want ot do type system directed emit.
two questions:
@mhegazy What is the spec issue here?
this is a question more than an issue. we do not support spread on strings. should we?
This still seems like a bug since we don't conform with ES6.
Of note - if you are going to consider surrogate pairs here, there's a number of other places where it may be significant which might require polyfill for ES3/ES5. For example,
const guitar = '\u{1F3B8}';
for (let symbol of guitar) {
console.log(symbol); //expect one call here (TypeScript 1.5 ES5 target makes one call per surrogate pair)
}
Considering that, it might be best to restrict this to ES6+ target.
Was this implemented in 2.0?
Spread on strings is quite important, but I guess some work need to be done to get the sample below to work in non-ES6 environments.
let str = 'x\uD83D\uDE80y';
// ES5: \uD83D\uDE80 are (incorrectly) reversed
console.log(str.split('').reverse().join(''));
// 'y\uDE80\uD83Dx'
// ES6: order of \uD83D\uDE80 is preserved
console.log([...str].reverse().join(''));
// 'y\uD83D\uDE80x'
Just so people understand what we're up against, it's surrogate pairs. Taking the example of "a๐" (a "normal" character followed by a surrogate pair), it has some fairly odd behavior (shown here in Chrome console):

Specifically notice that:
length is 3 but there are only 2 glyphsArray#slice produces 3 elementsIn Dojo, we have a for ... of shim which provides iteration over strings that meets the ES6 spec. Obviously emitting that for strings is rather complicated to be able to spread them. I don't know if that helps at all, but I guess something like this could be adapted into a helper function.
@RyanCavanaugh There's no problem with this... This is a validated spec of ES6. The spread operator is viable on any iterable object. The string is one.
Moreover, the [..."a๐"] // ["a", "๐"] is totally valid and should not be compared to the length of the string or the Array.prototype.splice method.
@ChibiBlasphem Ryan is not suggesting that [ ...'a๐' ] is invalid, it is just not easily down-emittable.
When your target is es2015 or beyond, there is no issue with this and TypeScript allows it. When your target is es5 or es3, there is no easy down emit that can easily spread a string, because what is available natively, does not deal with surrogate pairs. The only way to deal with it is to emit some sort of helper function that detects the surrogate pairs and splits up the characters properly.
You can check how es6 is doing it.
They can transpile it to es5 version. For es3 I don't really know if it's possible.
You can check how es6 is doing it.
ES6 is using iterators. It isn't doing it in user space. As I linked to, there are ways to do it, but the down emit is rather complex. It would look something like this (which is fine for ES5 and ES3), which handles the pairs correctly, but this would be another helper for a rather limited situation:
function __spreadString(str) {
var l = str.length;
var result = [];
for (let i = 0; i < l; ++i) {
var char = str[i];
if ((i + 1) < l) {
var code = char.charCodeAt(0);
if ((code >= 0xD800) && (code <= 0xDBFF)) {
char += str[++i];
}
}
result.push(char);
}
return result;
}
console.log(__spreadString('a๐')); // ["a", "๐"]
console.log(__spreadString('x\uD83D\uDE80y').reverse()); // ["y", "๐", "x"]
Bump. So why isn't this supported yet? I was quite surprised that the spread operator works on strings in ES6 but not TS.
@JakeStoeffler the comments above make that clear... supporting surrogate pairs in ES5 properly is complicated to ensure the behaviour is consistent with the spec. It would a) require a helper function and b) have a typed based emit which TypeScript is fundamentally opposed to.
This issue title confused me for a second.
This is about downlevel emit, not about supporting it at the type level. If --downlevelIterators, or --target is es2015 or newer it will behave correctly.
Is it so complicated to take Babel implementation which can handle this properly? ๐ญ
Would be nice to at least add a warning that ES5/ES3 target can't emit this correctly. It's quite an old issue at this point.
@rbuckton any chance your work on array spread might lead to looking into this at some point?
Most helpful comment
This still seems like a bug since we don't conform with ES6.