TypeScript pour… ou avec index / clé?

146

Comme décrit ici, TypeScript introduit une boucle foreach:

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

Mais n'y a-t-il pas d'index / clé? Je m'attendrais à quelque chose comme:

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

Réponses:

274

.forEach a déjà cette capacité:

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

Mais si vous voulez les capacités de for...of, alors vous pouvez maple tableau à l'index et à la valeur:

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

C'est un peu long, il peut donc être utile de le mettre dans une fonction réutilisable:

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

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

Version itérable

Cela fonctionnera lorsque vous ciblez ES3 ou ES5 si vous compilez avec l' --downlevelIterationoption du compilateur.

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 vous pouvez cibler les environnements ES6 +, vous pouvez utiliser la .entries()méthode décrite dans la réponse d'Arnavion .

David Sherret
la source
Mais TypeScript compile "for ... of" en un simple "for" qui a un index var _i. Il serait donc facile pour les développeurs TypeScript de nous laisser utiliser ce _i. Voir l'exemple de l'aire de jeux: bit.ly/1R9SfBR
Mick
2
@Mick cela dépend de la cible. Lors du transpilage vers ES6, il ne le fait pas. La raison de ce code supplémentaire lors de la transpilation est uniquement de faire fonctionner le code ES6 dans les versions précédentes.
David Sherret
3
Comment pouvez-vous faire une pause; dans ce forEach?
João Silva
Aussi une bonne réponse stackoverflow.com/questions/34348937/…
Christopher Grigg
@ JoãoSilva vous pouvez utiliser Array.some()et renvoyer false à l'itération que vous souhaitez arrêter. Ce n'est pas aussi clair ou joli qu'un, breakmais cela ferait le travail. Personnellement, je n'aime pas ça, je réécrirais probablement l'itération d'une autre manière :) voir stackoverflow.com/questions/2641347/…
Neek
35

"Old school javascript" à la rescousse (pour ceux qui ne sont pas familiers / amoureux de la programmation fonctionnelle)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}
Sylvain
la source
2
Je préfère en fait cette réponse la meilleure. Pas d'utilisation de méthodes supplémentaires juste pour générer un index pour chaque élément.
bluegrounds
Merci veryyyy muuuchh! Nous ne savions pas cela :)
TSR
14

Vous pouvez utiliser l' opérateur TypeScript for..in pour accéder à l'index lorsque vous traitez des collections.

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

Production:

 0: 7
 1: 8
 2: 9

Voir la démo

Karanvir Kang
la source
Sachez que "i" est une chaîne et non un int avec une boucle for..in. L'exécution d'une opération arithmétique avec "i" entraînera une concaténation de chaînes. (i + 1) sera égal à "01" par exemple quand i = 0
Stéphane
for..inpeut également vous donner plus que ce à quoi vous vous attendiez car il inclut également toutes les fonctions déclarées sur un objet. Par exemple:for (var prop in window.document) { console.log(prop); }
Ken Lyon
5

Ou une autre solution à l'ancienne:

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