36

How do you iterate over a set in TypeScript? for..of does not work:

'Set<string>' is not an array type or a string type

.forEach is not acceptable, because it hides this. I'd prefer not to do a while loop in a try catch block. What am I missing? It can't it possibly so clumsy as to require try {while} catch {}.

wonea
  • 4,783
  • 17
  • 86
  • 139
Programmer9000
  • 1,959
  • 3
  • 17
  • 27

4 Answers4

51

@SnareChops was mostly correct:

mySet.forEach(function(item){
    // do something with "this"
}, **this**);

This works.

I'm guessing:

for(item of mySet.values()){
}

Would work if I weren't working with es-shim stuff which is messing everything up for me. But the shim stuff is prescribed by the Angular 2 crew so ¯_(ツ)_/¯

The only other thing that worked was:

for (var item of Array.from(set.values())) {
}

or something like that, which is just terrible.

Niels Steenbeek
  • 4,692
  • 2
  • 41
  • 50
Programmer9000
  • 1,959
  • 3
  • 17
  • 27
4

Extending the most upvoted answer, it is also type-safe if we use let for the iteration variable, so:

for (let elem of setOfElems) {
   ... do anything with elem...
}

This will guarantee that elem will have the type X, if setOfElems was declared as Set<X>.

peterh
  • 11,875
  • 18
  • 85
  • 108
3

You can still use .forEach with the correct this by using a regular function instead of an arrow function

mySet.forEach(function(item){
    expect(this).toEqual(item);
});

Compared to

class MyClass{
    ...
    doSomething():{
        mySet.forEach((item) => {
            expect(this instanceof MyClass).toEqual(true);
        });
    }
}

Another way to iterate is to use a for loop over the values

for(item of mySet.values()){
    ...
}

More information on iterating Set with foreach can be found here

SnareChops
  • 13,175
  • 9
  • 69
  • 91
  • I appreciate the quick response but I've found the following to be true: Approach 1: "this" is not preserved, and i think it would normally be that lambda's are the ones to preserve "this" Approach 2: This doesn't compile for me. The only way I've found that works so far aside from the "while" approach has been: for (var key of Array.from(this.keys.values())) and that's far from desirable since I think it creates a new array and Array.from isn't fully supported everywhere. – Programmer9000 Feb 04 '16 at 06:09
  • The follwing __ to be true? – SnareChops Feb 04 '16 at 06:11
1

You can use for ... of in TypeScript if you add "es6" as "lib" in your compiler options, and "es6" as target. You may also use "es2015.iterable" in place of "es6" in your lib if that better suits your needs.

For example (this would be your tsconfig.json):

{
    "compilerOptions": {
        "target": "es6",
        "lib": [
            "es6",
            "dom"
        ]
    },
    "exclude": [
        "node_modules"
    ]
}

Related issue on GitHub: https://github.com/Microsoft/TypeScript/issues/12707

Newbyte
  • 2,421
  • 5
  • 22
  • 45