TypeScript, recorriendo un diccionario

186

En mi código, tengo un par de diccionarios (como se sugiere aquí ) que está indexado en cadena. Debido a que este es un tipo un poco improvisado, me preguntaba si hay alguna sugerencia sobre cómo podría recorrer cada clave (o valor, de todas formas necesito las claves). Cualquier ayuda apreciada!

myDictionary: { [index: string]: any; } = {};
ben657
fuente
¿Intentaste for (var key in myDictionary) { }:? Dentro del bucle, usaría keypara obtener la clave y myDictionary[key]obtener el valor
Ian
@Ian Acabo de intentar eso, no parece estar funcionando. Sin errores, pero nada se ejecuta dentro de la declaración
ben657
1
@ Ian Ah, lo siento, algún código en otro lugar estaba jugando con eso. Eso funciona perfectamente! ¿Te importaría darle una respuesta para que yo pueda elegirlo?
ben657

Respuestas:

296

Para recorrer la clave / valores, use un for inciclo:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
Ian
fuente
8
Esto no es seguro en general; necesita la prueba hasOwnProperty (como en la respuesta de Jamie Stark) o algo más.
Don Hatch
20
@DonHatch En realidad, es muy seguro en general. No es seguro en casos muy específicos (como cuando incluye bibliotecas que modifican prototipos incorrectamente, o deliberadamente modifican prototipos incorrectamente). Depende del desarrollador si hinchar su código con comprobaciones probablemente innecesarias
Ian
1
@Ian: creo que no lo usaría sin garantías adicionales, ya que parece un accidente a la espera de que suceda, por ejemplo, si el código llega a una función de utilidad, y luego alguien pasa esa función a un diccionario que no es simplemente un Objeto, sino algo con propiedades adicionales. Sí, como usted dice, depende del desarrollador sopesar la probabilidad y la gravedad de tal escenario. Para mí, el enfoque menos oneroso mental es comportarme como si se garantizara que tal escenario sucedería en todos los casos, menos en lo que pensar.
Don Hatch
55
@Ian El problema es que hay demasiadas bibliotecas que modifican los prototipos de objetos. Parece una mala idea abogar por este tipo de patrón cuando existen alternativas mucho mejores y simples, como Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Si debe mostrar este método, al menos mencione los riesgos y las mejores alternativas para aquellos que aún no conocen mejor.
Yona Appletree
8
Ya tenemos es6 y TypeScript. ¿Por qué el problema de escribir hasOwnProperty todo el tiempo permanece sin resolver? Incluso en 2017 y con toda la atención a JS. Estoy muy 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
fuente
Esta es la solución que estaba buscando, ya que me permitirá ordenar las claves antes de la iteración
Andrew
FYI, esto no es compatible con el campo de juegos TypeScript en este momento.
Seanny123
1
Vea aquí cómo hacer Object.entriesque funcione en TypeScript
Alex Klaus
Esto es perfecto
Piyush Choudhary
67

¿Qué tal esto?

for (let [key, value] of Object.entries(obj)) {
    ...
}
Radon Rosborough
fuente
1
Requiere lib es2017 en tsconfig. Ver stackoverflow.com/questions/45422573/…
Stéphane
Esto es lo que necesitaba para superar el error de mecanografía en obj [clave] "Sin firma de índice ..." porque configuré explícitamente mi tipo de obj como {[clave: cadena]: cadena} y no quería usar {[clave: cadena]: cualquiera}. Con esto solo puedo acceder al 'valor'. Gracias
ggedde
Y si desea ignorar keyen absoluto, simplemente deje en blanco: [ , value]. (Gracias a este comentario del problema ).
Dominik
51

Hay una advertencia para el ciclo de clave / valor que Ian mencionó. Si es posible que los Objetos tengan atributos asociados a su Prototipo, y cuando use el inoperador, estos atributos se incluirán. Por lo tanto, querrá asegurarse de que la clave sea un atributo de su instancia, y no del prototipo. Los IE más antiguos son conocidos por indexof(v)aparecer como una clave.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}
Jamie Starke
fuente
3
No estoy tratando de dividir los pelos, pero como estamos hablando de script de tipo, ¿no deberías usar let key en lugar de var key? Buena respuesta gracias.
Luke Dupin
3
De hecho, con la versión actual de la secuencia de comandos tipo keyy el valuepuede ser const.
Patrick Desjardins
Es mejor no llamar al hasOwnPropertycheque desde el objeto de destino, sino hacer esto: de lo ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...contrario, si está utilizando eslint con la no-prototype-builtinsregla, emitirá un error.
sceee
6

La forma más corta de obtener todos los valores de diccionario / objeto:

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

Para obtener las llaves:

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

Ians Answer es buena, pero debe usar const en lugar de permitir la clave porque nunca se actualiza.

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