TypeScript, fazendo loop em um dicionário

186

No meu código, tenho alguns dicionários (como sugerido aqui ), que são indexados por String. Por ser um tipo improvisado, fiquei imaginando se havia alguma sugestão sobre como seria capaz de percorrer cada chave (ou valor, tudo o que preciso para as chaves). Qualquer ajuda apreciada!

myDictionary: { [index: string]: any; } = {};
ben657
fonte
Você tentou for (var key in myDictionary) { }:? Dentro do loop, você pode usar keypara obter a chave, e myDictionary[key]para obter o valor
Ian
@ Ian Apenas tentei isso, não parece estar funcionando. Sem erros, mas nada é executado dentro do comunicado
ben657
1
@ Ian Ah, desculpe, algum código em outro lugar estava mexendo com ele. Isso funciona perfeitamente! Gostaria de fazer uma resposta para que eu possa escolher?
ben657

Respostas:

296

Para fazer um loop sobre a chave / valores, use um for inloop:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
Ian
fonte
8
Isso não é seguro em geral; ele precisa do teste hasOwnProperty (como na resposta de Jamie Stark) ou de outra coisa.
Don Hatch
20
@ DonHatch Na verdade, é muito seguro em geral. Não é seguro em casos muito específicos (como quando você inclui bibliotecas que modificam protótipos incorretamente ou propositadamente modificam protótipos incorretamente). É até o desenvolvedor se a inchar seu código com cheques mais provável-desnecessários
Ian
1
@Ian - Meu pensamento é que eu não o usaria sem salvaguardas adicionais, pois parece um acidente esperando para acontecer, por exemplo, se o código entrar em uma função utilitária e alguém passar essa função em um dicionário que não é simplesmente um Objeto, mas algo com propriedades adicionais. Sim, como você diz, cabe ao desenvolvedor avaliar a probabilidade e a gravidade de tal cenário. Para mim, a abordagem menos onerosa é comportar-se como se esse cenário fosse garantido em todos os casos - menos em que pensar.
Don escotilha
5
@Ian O problema é que existem muitas bibliotecas que modificam os protótipos de objetos. Parece uma má ideia advogar esse tipo de padrão quando existem alternativas muito melhores e simples, como Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Se você precisar mostrar esse método, mencione pelo menos os riscos e as melhores alternativas para quem ainda não conhece.
usar o seguinte código
8
Já temos es6 e TypeScript. Por que o problema de escrever hasOwnProperty o tempo todo permanece sem solução? Mesmo em 2017 e com toda atenção ao JS. Estou tão decepcionado.
Gherman
170

<ES 2017 :

Object.keys(obj).forEach(key => {
  let value = obj[key];
});

> = ES 2017 :

Object.entries(obj).forEach(
  ([key, value]) => console.log(key, value);
);
Stephen Paul
fonte
Esta é a solução que eu estava procurando uma vez que irá permitir-me para classificar as chaves antes de iteração
Andrew
FYI, neste momento não há suporte para o playground TypeScript.
precisa saber é o seguinte
1
Veja aqui como fazer Object.entrieso trabalho à máquina
Alex Klaus
Isto é perfeito
Piyush Choudhary
67

Que tal agora?

for (let [key, value] of Object.entries(obj)) {
    ...
}
Radon Rosborough
fonte
1
Requer lib es2017 no tsconfig. Veja stackoverflow.com/questions/45422573/…
Stéphane
Era isso que eu precisava para superar o erro de texto datilografado na obj [key] "Sem assinatura de índice ..." porque eu defini explicitamente meu tipo de obj como {[key: string]: string} e não queria usar {[key: string]: qualquer}. Com isso, eu posso acessar 'valor'. Graças
ggedde
E se você deseja ignorar keyem tudo, simplesmente deixe em branco: [ , value]. (Graças a este comentário da questão .)
Dominik
51

Há uma ressalva no loop de chave / valor que Ian mencionou. Se for possível que os Objetos possuam atributos anexados ao seu Protótipo, e quando você usar o inoperador, esses atributos serão incluídos. Portanto, você deve garantir que a chave seja um atributo da sua instância, e não do protótipo. IEs mais antigos são conhecidos por indexof(v)aparecerem como uma chave.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}
Jamie Starke
fonte
3
Não estou tentando dividir os cabelos, mas como estamos falando de um script de tipo, você não deve usar a tecla let em vez da tecla var? Boa resposta, obrigado.
Luke Dupin
3
De fato, com a versão atual do script de tipo, o keye valuepode ser const.
Patrick Desjardins 03/03
É melhor não chamar a hasOwnPropertyverificação do objeto de destino, faça o seguinte: ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...Caso contrário , se você estiver usando eslint com no-prototype-builtinsregra, ele emitirá um erro.
sceee 30/04
6

Maneira mais curta de obter todos os valores de dicionário / objeto:

Object.keys(dict).map(k => dict[k]);
k06a
fonte
1

Para obter as chaves:

function GetDictionaryKeysAsArray(dict: {[key: string]: string;}): string[] {
  let result: string[] = [];
  Object.keys(dict).map((key) =>
    result.push(key),
  );
  return result;
}
Ribeiro
fonte
1

Resposta é boa, mas você deve usar const em vez de deixar a chave, porque ela nunca é atualizada.

for (const key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
finnk
fonte