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

Iterating ES6 Map object #6842

Closed
heruan opened this issue Feb 2, 2016 · 14 comments
Closed

Iterating ES6 Map object #6842

heruan opened this issue Feb 2, 2016 · 14 comments
Labels
External Relates to another program, environment, or user action which we cannot control.

Comments

@heruan
Copy link

heruan commented Feb 2, 2016

When I try to iterate over a Map object as described in MDN: Map, i.e.

let map = new Map<string, string>();

map.set("key", "value");

for (let value of map.values()) {
    console.debug(value);
}

the compiler complains:

Type 'IterableIterator<string>' is not an array type or a string type.

Is this a bug, or am I doing something wrong?

@RyanCavanaugh RyanCavanaugh added the External Relates to another program, environment, or user action which we cannot control. label Feb 2, 2016
@RyanCavanaugh
Copy link
Member

Works fine in master (not sure about the most recent release version). Also, there is no put in Map. Are you sure you're using the right .d.ts file?

@heruan
Copy link
Author

heruan commented Feb 2, 2016

I meant Map.set, sorry. I'm using v1.7.3, I'll try v1.7.5 and then v1.8.0-beta!

@Arnavion
Copy link
Contributor

Arnavion commented Feb 2, 2016

The error message sounds like you're targeting ES5 and forcing it to use lib.es6.d.ts to be able to get Map (or perhaps from some other .d.ts). TS doesn't support iterating IterableIterator with ES5 target, only strings and arrays.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 2, 2016

looks like a duplicate of #4947, or at least stemming from the same issue.

@Arnavion
Copy link
Contributor

Arnavion commented Feb 3, 2016

@mhegazy #4947 is to allow for-of on array-likes in ES5. Map.values() returns an iterator and is only available in ES6 anyway.

@heruan
Copy link
Author

heruan commented Feb 3, 2016

@Arnavion is right, targeting ES6 solves the problem. I'm now transpiling TS to ES6 and then ES6 to ES5 with Babel. Thank you!

@mischkl
Copy link

mischkl commented Oct 18, 2016

This seems pretty strange. Why should it be necessary to transpile to ES6 and then again with Babel (the process of which incidentally messes up source maps in our project) just in order to have a standard ES6 feature work? Isn't TypeScript supposed to be a superset of ES6 and the TypeScript compiler a drop-in replacement for Babel?

@kitsonk
Copy link
Contributor

kitsonk commented Oct 18, 2016

TypeScript is a syntactic superset of JavaScript, not a functional superset. When syntax and functionality intersect, there is a bit of a grey area. When targeting ES5, TypeScript assumes that only number indexed based objects (ArrayLike) can be down-emitted with for ... of because those are only the functional structures which are guaranteed to be supported by ES5.

#11209 discusses this in more detail with other possible solutions when you cross the syntactic/functional barrier of ES6.

@Arnavion
Copy link
Contributor

Indeed, even though TS emits ES5-compliant JS, that JS is not ES6-conformant. For example, the JS emitted for for-of even for arrays does not account for iterators because it assumes they don't exist. Babel works around this by requiring core-js to provide the ES6 functionality. TS should definitely not be considered a drop-in replacement for Babel.

@mischkl
Copy link

mischkl commented Oct 18, 2016

I'd be totally fine if core-js were a requirement. In fact we are using core-js already for exactly this reason. The problem is that it doesn't help much to have those (type-safe!) ES6 collections classes available, if it's not even possible to iterate over them.

@mischkl
Copy link

mischkl commented Oct 18, 2016

@Arnavion I've also described our trials and tribulations in greater detail in the linked issue (#11209). It's newer and has more active participants, so let's use that for future discussion. ;)

@kristianmandrup
Copy link

I got the error when using map, even when compiling to target: "ES6" in VSC

  mergeAll() {
    this.streams.values().map(stream => stream.subscribe(this.stream))
  }

Worked when I switched to a for loop instead (which I normally try to avoid to keep more functional)

    for (let stream of this.streams.values()) {
      stream.subscribe(this.stream)
    }

Any suggestions?

@dylanpyle
Copy link

Assuming you have a polyfill for newer Array features, one not-awful workaround I've come up with is to use the second mapFn argument to Array.from as a replacement for the lack of for...of support:

const map = new Map<string, number>();
map.set('a', 1);
map.set('b', 2);

Array.from(map.values(), (value: number) => {
  alert(value);
});

@kitsonk
Copy link
Contributor

kitsonk commented Jan 6, 2018

--downLevelIteration is a better solution @dylanpyle

This issue predates the availability of that feature.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
External Relates to another program, environment, or user action which we cannot control.
Projects
None yet
Development

No branches or pull requests

8 participants