Skip to content
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

for..of with iterators #3164

Closed
SergioMorchon opened this issue May 14, 2015 · 9 comments
Closed

for..of with iterators #3164

SergioMorchon opened this issue May 14, 2015 · 9 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@SergioMorchon
Copy link

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 .

@mhegazy
Copy link
Contributor

mhegazy commented May 21, 2015

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..

@mhegazy mhegazy added the Question An issue which isn't directly actionable in code label May 21, 2015
@SergioMorchon
Copy link
Author

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

@mvolkmann
Copy link

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.

@mvolkmann
Copy link

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.

@mhegazy
Copy link
Contributor

mhegazy commented Apr 20, 2017

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

@lhunath
Copy link

lhunath commented Sep 11, 2017

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?

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Sep 11, 2017

@lhunath you must specify the --downlevelIteration option.

@lhunath
Copy link

lhunath commented Sep 11, 2017

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?

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Sep 11, 2017

@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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants