#Why is tsc transpiling a `for of` loop on a Set into an attempt to access numeric keys?

2 messages · Page 1 of 1 (latest)

neat burrow
#
const foo = new Set;
foo.add("bar");
console.log(foo.size);
for (const val of foo) {
  console.log(`of ${val}`);
}
for (const key of foo) {
  console.log(`in ${key}`);
}
console.log(`entries ${foo.entries().next().value}`);

tsc is transpiling the above to

var foo = new Set;
foo.add("bar");
console.log(foo.size);
for (var _i = 0, foo_1 = foo; _i < foo_1.length; _i++) {
  var val = foo_1[_i];
  console.log("of ".concat(val));
}
for (var _a = 0, foo_2 = foo; _a < foo_2.length; _a++) {
  var key = foo_2[_a];
  console.log("in ".concat(key));
}
console.log("entries ".concat(foo.entries().next().value));

What could be causing this behavior? That use of numeric indexing looks completely invalid to me, and it results in zero iterations of both loops.
I confirmed this behavior persists with an empty or missing tsconfig.json

prime hollow
#

TypeScript's default "target" option with an empty tsconfig is "ES3", which doesn't have Set or Symbol.iterator.
Before TS fully knew what iterators were, it recognized for..of as a fancy loop over an array. In v2.3 TS gained support for iterators, but to avoid backwards compatibility breaks (and performance regressions!) the existing emit was kept.
The downlevelIteration option can be turned on to make the type of output you were probably expecting, however you should really instead set the target option to a non-ancient JS version