TypeScript: el elemento tiene implícitamente un tipo ‘cualquiera’ porque la expresión del tipo ‘cadena’ no se puede usar para indexar el tipo

5 minutos de lectura

avatar de usuario de prueba
prueba

tengo este codigo:

const color = {
    red: null,
    green: null,
    blue: null
};

const newColor = ['red', 'green', 'blue'].filter(e => color[e]);

el error esta en color[e] cerca de la parte inferior con el error:

El elemento tiene implícitamente un tipo ‘cualquiera’ porque la expresión de tipo ‘cadena’ no se puede usar para indexar el tipo ‘{ red: null; verde: nulo; azul: nulo; }’. No se encontró ninguna firma de índice con un parámetro de tipo ‘cadena’ en el tipo ‘{ red: null; verde: nulo; azul: nulo; }’.

Traté de buscar en todas partes en los documentos de TypeScript, pero ¿cómo se supone que debo interface esto para que pueda aceptar color[e]?

avatar de usuario de hugo
hugo

Puedes declarar colors como any decirle a TypeScript que se quite la espalda con este (también conocido como explícito cualquier):

const color : any = {
    red: null,
    green: null,
    blue: null
};

Pero si es posible, es preferible una tipificación fuerte:

const color : { [key: string]: any } = {
    red: null,
    green: null,
    blue: null
};

Más información sobre la indexación en TypeScript: índice de firmas


EDITAR: En esta respuesta a una pregunta similar, el autor sugiere usar un Map<,> – si eso se ajusta a su caso de uso.

  • { [key: string]: any }..? TypeScript lo tiene cubierto con el Record<string, any> escribe.

    – gastador

    10 de agosto de 2019 a las 0:11

  • Me topé con esto y el comentario anterior de @spender es realmente acertado. Pero, ¿alguien puede realmente explicar por qué esto resuelve el tipo y el uso { [key:string]: any } no es suficiente?

    – Aron Rotteveel

    14 oct 2022 a las 14:17

  • @AronRotteveel Record<string, any> es preferible porque es más legible, pero { [key:string]: any } debería funcionar también. Cuál elijas es simplemente una cuestión de estilo. ¿Quizás le dio a la clave un tipo no literal, como una unión de tipos? En ese caso, tendrías que escribir { [key in MyTypeUnion]: any }

    – hugo

    20 oct 2022 a las 11:51


El problema que tienes no es ese color es el tipo incorrecto, pero que TypeScript está infiriendo el tipo de ['red', 'green', 'blue'] ser string[]. A menudo, ese tipo de inferencia es deseable, ya que (por lo que sabe el compilador) es posible que desee empujar 'purple' en eso. Pero en este caso, le gustaría que el compilador supiera que los únicos miembros son los tres literales de cadena 'red', 'green'y 'blue'. Es decir, necesita un tipo al menos tan específico como Array<'red'|'green'|'blue'>.

Asumiendo que está usando TS3.4 o posterior, la forma más fácil de obtener este tipo de inferencia de tipo del compilador es usar un const afirmación:

const constAssertionTest = ["red", "green", "blue"] as const;
// const constAssertionTest: readonly ["red", "green", "blue"];

Él as const hace que el compilador infiera una tupla compuesto por exactamente los tres literales de cadena en la matriz, en el orden exacto que ha establecido. (Es incluso un tupla de solo lectura). Eso es lo suficientemente bueno para corregir su error:

const newColor = (['red', 'green', 'blue'] as const).filter(e => color[e]); // okay

Muy bien, espero que eso ayude. ¡Buena suerte!

Enlace al código

Sé que es una vieja pregunta, pero no estoy satisfecho con las otras respuestas. Por favor, evita el as palabra clave tanto como sea posible!

Veamos por qué nos encontramos con este error y qué hacer con él.

Motivo: ni la const ni la matriz de cadenas tienen un tipo.

Cuando no le da un tipo a una const, Typescript infiere su tipo en función de la valor inicial. Sabiendo eso, el error simplemente dice “hey, e podría ser cualquier cadena, incluso cadenas que no son parte del tipo inferido de su const”. ¿Qué pasa si e era igual a 'yellow' eso no se sabe en color tipo inferido?

Te puedo recomendar 3 formas de manejar esto:

1. Más simple pero no tan”Escribesolución “espíritu de guión”

Solo da un tipo string a las claves de su const, así:

const color: {[key:string]:null} = {
  red: null,
  green: null,
  blue: null
};

Hmmm… Eso funciona, pero podemos hacerlo mejor.

2. De camino a los tipos…

Dígale al compilador de TypeScript que está usando el llaves de el inferido tipo de la const con las palabras clave: keyof typeof.

En el ejemplo dado, eso sería:

const colorKeys: (keyof typeof color)[]  = ['red', 'green', 'blue'];

const newColor = colorKeys.filter((e) => color[e]);

¿Aún puedes hacer un pequeño esfuerzo extra? Ver siguiente punto.

3. Aquí está: ¡da tipos a tus objetos!

Crea una interfaz (o lo que necesites como tipo) y dásela a tu const. Luego, especifique el tipo de la matriz de cadenas con el keyof palabra clave:

interface Color {
  red:number|null;
  green:number|null;
  blue:number|null;
}
const color: Color = {
  red: null,
  green: null,
  blue: null
};

const colorKeys: (keyof Color)[]  = ['red', 'green', 'blue'];

const newColor = colorKeys.filter((e) => color[e]);

Gracias por todas las excelentes respuestas. Nuevo en mecanografiado y arreglé con éxito mi primer bloqueo de carretera.

  // in javascript world this is what I used to do.
  let values1 = products.reduce((acc, product) => {
      acc[product] = 1;
  //  ^  --> Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  // No index signature with a parameter of type 'string' was found on type '{}'.  TS7053

      return acc;
  }, {})

  // in typescript world I needed an extract type specification for 'acc'
  let values2 = products.reduce((acc: { [key: string]: number}, product) => {
      acc[product] = 1; //No more error
      return acc;
  }, {})

Aquí hay otra solución usando Record

const color: Record<string, null> = {
    red: null,
    green: null,
    blue: null
}

¿Ha sido útil esta solución?