Búsqueda de sitios web

javascript - TypeScript - El elemento tiene implícitamente un tipo 'any' porque una expresión de tipo 'string' no se puede usar para indexar el tipo


Tengo este código:

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

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

El error está en color[e] cerca de la parte inferior con el error:

El elemento tiene implícitamente un tipo 'any' porque no se puede usar una expresión de tipo 'string' para indexar el tipo '{ red: null; green: null; blue: null; }'. No se encontró ninguna firma de índice con un parámetro de tipo 'string' en el tipo '{ red: null; green: null; blue: null; }'.

Intenté buscar en todas partes en la documentación de TypeScript, pero ¿cómo se supone que debo interface esto para que pueda aceptar color[e]?

Respuesta #1

Puedes declarar colors como any para decirle a TypeScript que te deje en paz con esto (también conocido como any explícito):

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

Pero si es posible, se prefiere la tipificación fuerte:

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

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

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

Respuesta #2

El problema que tienes no es que color sea del tipo incorrecto, sino que TypeScript está infiriendo el tipo de ['red', 'green', 'blue'] como string[]. A menudo, ese tipo de inferencia es deseable, ya que (según todo lo que sabe el compilador) podrías querer agregar 'purple' a él. Pero en este caso, te gustaría que el compilador supiera que los únicos miembros son los tres literales de cadena 'red', 'green' y 'blue'. Es decir, necesitas un tipo al menos tan específico como Array<'red'|'green'|'blue'>.

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

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

El as const hace que el compilador infiera una tupla compuesta exactamente por las tres cadenas literales en el arreglo, en el orden exacto que has establecido. (Incluso es una tupla de solo lectura). Eso es suficiente para corregir tu error:

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

Está bien, espero que eso ayude. ¡Buena suerte!

Enlace al código

Respuesta #3

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

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

Razón: ni la constante ni el arreglo de cadenas tienen un tipo.

Cuando no le das un tipo a un const, Typescript infiere su tipo basado en el valor inicial. Sabiendo eso, el error solo dice "oye, e podría ser cualquier cadena, incluso cadenas que no forman parte del tipo inferido de tu const". ¿Qué pasa si e fuera igual a 'yellow' que no se conoce en el tipo inferido color?

Puedo recomendarte 3 formas de manejar esto:

1. La solución más simple pero no tan "Typescript Espíritu"

Simplemente da un tipo string a las claves de tu const, así:

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

Mmmm... Eso funciona, pero podemos hacerlo mejor.

2. En el camino hacia los tipos...

Dile al compilador de Typescript que estás usando las claves de el tipo de la constante 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]);

¿Puedes hacer todavía un pequeño esfuerzo extra? Ve el siguiente punto.

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

Crea una interfaz (o lo que necesites como tipo) y asígnala a tu const. Luego, especifica el tipo del array de cadenas con la palabra clave keyof :

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]);

Artículos relacionados