281

As described here TypeScript introduces a foreach loop:

var someArray = [9, 2, 5];
for (var item of someArray) {
    console.log(item); // 9,2,5
}

But isn't there any index/key? I would expect something like:

for (var item, key of someArray) { ... }

5 Answers 5

480

.forEach already has this ability:

const someArray = [9, 2, 5];
someArray.forEach((value, index) => {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
});

But if you want the abilities of for...of, then you can map the array to the index and value:

for (const { index, value } of someArray.map((value, index) => ({ index, value }))) {
    console.log(index); // 0, 1, 2
    console.log(value); // 9, 2, 5
}

That's a little long, so it may help to put it in a reusable function:

function toEntries<T>(a: T[]) {
    return a.map((value, index) => [index, value] as const);
}

for (const [index, value] of toEntries(someArray)) {
    // ..etc..
}

Iterable Version

This will work when targeting ES3 or ES5 if you compile with the --downlevelIteration compiler option.

function* toEntries<T>(values: T[] | IterableIterator<T>) {
    let index = 0;
    for (const value of values) {
        yield [index, value] as const;
        index++;
    }
}

Array.prototype.entries() - ES6+

If you are able to target ES6+ environments then you can use the .entries() method as outlined in Arnavion's answer.

Sign up to request clarification or add additional context in comments.

6 Comments

But TypeScript compiles "for ... of" to a simple "for" which has an index var _i. So it would be easy for TypeScript developers to let us use this _i. See playground example: bit.ly/1R9SfBR
@Mick it depends on the target. When transpiling to ES6 it doesn't do that. The reason for that extra code when transpiling is only to get the ES6 code to work in past versions.
How can you do a break; in that forEach?
@JoãoSilva you can use Array.some() and return false at the iteration you want to stop. It's not nearly as clear or pretty as a break but it would get the job done. Personally I don't like it, I'd probably re-write the iteration in some other way :) see stackoverflow.com/questions/2641347/…
|
103

See: Array.prototype.entries()

for (const [index, item] of someArray.entries()) { ... }

In TS this requires targeting ES2015 since it requires the runtime to support iterators, which ES5 runtimes don't. You can of course use something like Babel to make the output work on ES5 runtimes.

1 Comment

If you target es5, enable downLevelIteration explicitly in tsconfig. stackoverflow.com/a/49221814/3850405
73

"Old school javascript" to the rescue (for those who aren't familiar/in love of functional programming)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}

2 Comments

I actually prefer this answer the best. No using of extra methods just to generate an index for each element.
Thank youuu veryyyy muuuchh! We did not know this :)
22

You can use the for..in TypeScript operator to access the index when dealing with collections.

var test = [7,8,9];
for (var i in test) {
   console.log(i + ': ' + test[i]);
} 

Output:

 0: 7
 1: 8
 2: 9

See Demo

2 Comments

Be aware that "i" is a string not an int with for..in loop. Performing arithmetic operation with "i" will result in string concatenation. (i + 1) will be equal to "01" for example when i = 0
for..in can also give you more than you were expecting as it includes all functions declared on an object as well. For example: for (var prop in window.document) { console.log(prop); }
12

Or another old school solution:

var someArray = [9, 2, 5];
let i = 0;
for (var item of someArray) {
    console.log(item); // 9,2,5
    i++;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.