Typescript: for..of with iterators

Created on 14 May 2015  路  9Comments  路  Source: microsoft/TypeScript

It would be nice if the new sintax for (let value of values) works with iterators; ie:

for (let value of myMap.values()) {
    doSomething(value);
}

Related with #2695 .

Question

Most helpful comment

I find this really disappointing. I can use for-of with any iterable and target ES5 with Traceur and Babel today. I'm interested in proposing that our team switch from Traceur to TypeScript, but this limitation in TypeScript will stop that from happening. When TypeScript says it aims to be a superset of ES6, I think that needs to include the ability to target ES5 browsers for all the ES6 features it supports.

All 9 comments

This is already allowed if your target is ES6:

interface MyMap<T> {
    values(): Iterable<T>;
}
var myMap: MyMap<string>;

for (let value of myMap.values()) {
    var s: string = value;
}

The reason why this is not allowed in ES5/ES3 are:

  • One of the TypeScript axioms is to not do type-directed emit. i.e. that the emitted code is not dependent on the what the type system thinks about your code, but rather as a syntactic transformation of your input source.
  • Doing the full iterator emulation will mean that we have to depend on a pollyfill for Symbol, again another quality we like to keep
  • The generated full iteration logic is not cheep, you need to call next() and check done, if it fails return if not use the value. this is additional dispatch, two property lookups, and an object allocation on every iteration of a loop. We have tried to keep the emitted code simple and relatable to the source specially in performance characteristics
  • Finally to do all of that on custom iterable objects, we still need to do it on Arrays, since Arrays do not have this support in ES5/ES3, and we do not want to do type-directed emit, we need to convert an array to an iterable, which is drastically slower than your normal for loop. and the main issue is that is not clear from looking at a loop on an array that it would incur this cost.

As a result of these factors, in ES3/ES5 only arrays are allowed in for..of loops (as the most common iterable objects available in the JS language today); as for targeting ES6 (i.e. with runtime engine support for iterables and iterable arrays) custom iterables are allowed in addition to Array, string, map and set,..etc..

Understood...
@mhegazy Thank you a lot for your detailed response!!!

I find this really disappointing. I can use for-of with any iterable and target ES5 with Traceur and Babel today. I'm interested in proposing that our team switch from Traceur to TypeScript, but this limitation in TypeScript will stop that from happening. When TypeScript says it aims to be a superset of ES6, I think that needs to include the ability to target ES5 browsers for all the ES6 features it supports.

I guess I could use TypeScript to target ES6 and then run that output through Traceur or Babel. I really don't want to have to do that though.

As an update for this issue, the iterator protocol is now supported for target ES3/ES5 using --downlevelIteration. See #12346 for more info.

It looks like this is supposed to be fixed for TS 2.3, but I'm running TS 2.3.3 and

      for (let [ i, observationPoint ] of observationPointsList.entries())
        observationPoints[ observationPoint.spot || (i + 1) ] = observationPoint;

where observationPointsList is an ObservationPointModel[], yields:

[11:30:56]  typescript: src/models/observation-set.ts, line: 44 
            Type 'IterableIterator<[number, ObservationPointModel]>' is not an array type or a string type. 

Am I missing something?

Ah, indeed. I can't see in this documentation or #12346 - why is this hidden behind an option as opposed to standard behaviour? Will this always remain optional?

@lhunath it is in the official release information for 2.3. It is optional because it has a very significant impact on the size of generated code, and potentially on performance, for all uses of iterables (including arrays). I find the tradeoff to be worth the increased expressiveness, but making existing code slower and more complex seems like reasonable justification for there being a flag.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MartynasZilinskas picture MartynasZilinskas  路  3Comments

wmaurer picture wmaurer  路  3Comments

siddjain picture siddjain  路  3Comments

Zlatkovsky picture Zlatkovsky  路  3Comments

dlaberge picture dlaberge  路  3Comments