179

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) { ... }
Mick
  • 5,521
  • 5
  • 29
  • 53

5 Answers5

336

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

David Sherret
  • 82,097
  • 24
  • 165
  • 160
  • 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 Mar 20 '16 at 16:16
  • 2
    @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. – David Sherret Mar 20 '16 at 16:26
  • 3
    How can you do a break; in that forEach? – João Silva Aug 01 '17 at 10:45
  • Also a good answer https://stackoverflow.com/questions/34348937/access-to-es6-array-element-index-inside-for-of-loop – Christopher Grigg Mar 01 '18 at 05:09
  • @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 https://stackoverflow.com/questions/2641347/short-circuit-array-foreach-like-calling-break – Neek Mar 06 '20 at 03:15
  • @Neek Yeah, at the time I ended up just throwing an exception and catching it, anyways, it was almost 2 years ago so I have learned a few tricks for it already ;) – João Silva Mar 06 '20 at 12:48
46

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries

for (var [key, 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.

Arnavion
  • 2,721
  • 21
  • 26
  • If you target es5, enable `downLevelIteration` explicitly in `tsconfig`. https://stackoverflow.com/a/49221814/3850405 – Ogglas Dec 11 '20 at 10:28
43

"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];
}
Kamil Kiełczewski
  • 53,729
  • 20
  • 259
  • 241
Sylvain
  • 1,049
  • 2
  • 15
  • 24
14

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

Karanvir Kang
  • 1,841
  • 17
  • 16
  • 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 – Stéphane Jan 22 '19 at 15:27
  • `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); }` – Ken Lyon Jun 28 '19 at 16:56
8

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++;
}
Galdor
  • 1,322
  • 2
  • 17
  • 30