¿TypeScript para ... de con índice / clave?

146

Como se describe aquí, TypeScript presenta un bucle foreach:

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

¿Pero no hay ningún índice / clave? Esperaría algo como:

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

Respuestas:

274

.forEach ya tiene esta habilidad:

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

Pero si desea las habilidades de for...of, entonces puede mapcolocar la matriz en el índice y el valor:

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

Eso es un poco largo, por lo que puede ser útil ponerlo en una función reutilizable:

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

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

Versión Iterable

Esto funcionará cuando apunte a ES3 o ES5 si compila con la --downlevelIterationopción del compilador.

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 +

Si puede apuntar a entornos ES6 +, puede usar el .entries()método como se describe en la respuesta de Arnavion .

David Sherret
fuente
Pero TypeScript compila "para ... de" a un simple "para" que tiene un índice var _i. Por lo tanto, sería fácil para los desarrolladores de TypeScript dejarnos usar este _i. Ver ejemplo de patio de juegos: bit.ly/1R9SfBR
Mick
2
@Mick depende del objetivo. Al transpirar a ES6 no hace eso. La razón de ese código adicional al transpilar es solo para que el código ES6 funcione en versiones anteriores.
David Sherret
3
¿Cómo puedes hacer un descanso? en eso para cada uno?
João Silva el
También una buena respuesta stackoverflow.com/questions/34348937/…
Christopher Grigg
@ JoãoSilva puede usar Array.some()y devolver falso en la iteración que desea detener. No es tan claro o bonito como un breakpero podría hacer el trabajo. Personalmente no me gusta, probablemente volvería a escribir la iteración de alguna otra manera :) ver stackoverflow.com/questions/2641347/…
Neek
35

"Old school javascript" al rescate (para aquellos que no están familiarizados / aman la programación funcional)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}
Sylvain
fuente
2
De hecho, prefiero esta respuesta la mejor. No utilizar métodos adicionales solo para generar un índice para cada elemento.
bluegrounds
Gracias muuuuuuuuuuuuuuuu! No sabíamos esto :)
TSR
14

Puede usar el operador for..in TypeScript para acceder al índice cuando trabaje con colecciones.

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

Salida:

 0: 7
 1: 8
 2: 9

Ver demo

Karanvir Kang
fuente
Tenga en cuenta que "i" es una cadena no un int con for..in loop. Realizar una operación aritmética con "i" dará como resultado la concatenación de cadenas. (i + 1) será igual a "01", por ejemplo, cuando i = 0
Stéphane
for..intambién puede darle más de lo que esperaba, ya que también incluye todas las funciones declaradas en un objeto. Por ejemplo:for (var prop in window.document) { console.log(prop); }
Ken Lyon
5

O otra solución de la vieja escuela:

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