TypeScript para… com índice / chave?

146

Conforme descrito aqui, o TypeScript apresenta um loop foreach:

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

Mas não há nenhum índice / chave? Eu esperaria algo como:

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

Respostas:

274

.forEach já tem essa capacidade:

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

Mas se você quiser as habilidades de for...of, poderá mapcolocar o array no índice e valor:

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

Isso é um pouco longo, por isso pode ajudar a colocá-lo em uma função reutilizável:

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

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

Versão Iterável

Isso funcionará ao direcionar o ES3 ou o ES5 se você compilar com a --downlevelIterationopção de 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 +

Se você conseguir segmentar ambientes ES6 +, poderá usar o .entries()método descrito na resposta de Arnavion .

David Sherret
fonte
Mas o TypeScript compila "para ... de" para um simples "para" que possui um índice var _i. Portanto, seria fácil para os desenvolvedores do TypeScript nos deixar usar esse _i. Veja o exemplo do playground: bit.ly/1R9SfBR
Mick
2
@ Rick depende do alvo. Ao transpilar para o ES6, isso não acontece. O motivo desse código extra ao transpilar é apenas fazer com que o código ES6 funcione em versões anteriores.
David Sherret
3
Como você pode fazer uma pausa? nesse forEach?
João Silva
Também é uma boa resposta stackoverflow.com/questions/34348937/…
Christopher Grigg
@ JoãoSilva, você pode usar Array.some()e retornar false na iteração que deseja parar. Não é tão claro ou bonito como um, breakmas faria o trabalho. Pessoalmente, eu não gosto, provavelmente reescreveria a iteração de alguma outra maneira :) veja stackoverflow.com/questions/2641347/…
Neek
35

"Javascript da velha escola" para o resgate (para quem não conhece / gosta de programação funcional)

for (let i = 0; i < someArray.length ; i++) {
  let item = someArray[i];
}
Sylvain
fonte
2
Na verdade, eu prefiro essa resposta da melhor maneira. Não é possível usar métodos extras apenas para gerar um índice para cada elemento.
bluegrounds 11/09/19
Obrigado muuuchh muuuchh! Não sabíamos disso :)
TSR
14

Você pode usar o operador for..in TypeScript para acessar o índice ao lidar com coleções.

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

Resultado:

 0: 7
 1: 8
 2: 9

Ver demonstração

Karanvir Kang
fonte
Esteja ciente de que "i" é uma sequência que não é um int com for..in loop. Executar operações aritméticas com "i" resultará em concatenação de cadeias. (i + 1) será igual a "01", por exemplo, quando i = 0
Stéphane
for..intambém pode oferecer mais do que você esperava, pois inclui também todas as funções declaradas em um objeto. Por exemplo:for (var prop in window.document) { console.log(prop); }
Ken Lyon
5

Ou outra solução da velha escola:

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