microsoft / microsoft/TypeScript

Confusing enum reverse string lookup behaviour in strict mode

Abierto
#29,094 6 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Domain: Error Messages Experience Enhancement Suggestion
Lenguaje dominante
Go
Estrellas
111k
Forks
14.3k
Merge medio
2 d 4 h
PR fusionados (30 d)
132

Descripción

Summary

Code below.

Typescript in --strict mode will reject enum reverse lookups using arbitrary strings with this very confusing error message:

Element implicitly has an 'any' type because index expression is not of type 'number'.

A workaround is to cast the string to a subset of all possible enum keys but that's impractical with large enums (or is there an easy way to say "any key of enum X" in TS?).

My real world use case: I have a react app with a <select> filter on various items, and a bunch of <option> values, all of which are part of an integer enum. I have to use the string representation in the dom, so the state of the filter has to be the string representation. When I check the item's enum value I already know it can only be one of those enum members.

This report is three-fold:

  1. Is this behaviour intended? There are cases where it can definitely catch a reverse lookup that can fail.
  2. If it is intended, then what is the correct way to declare that the lookup will always be valid? let typeFilter: "FOO" | "BAR" = "FOO" is impractical and increases risk of errors.
  3. Regardless of the above, the error message should be fixed. The element highlighted (typeFilter) does not in fact have an "any" type, and Type[typeFilter] will not be any either (in fact, Type[typeFilter] as Type does not fix it). An error such as "Reverse lookup on enum Type may fail because typeFilter is of type 'string'" is much clearer already.

Details

TypeScript Version: 3.2.2

Search Terms: enum reverse string lookup

Code

// test.ts
// Compile with `tsc --strict test.ts`
export enum Type {
	FOO = 0,
	BAR = 1,
}

const Test = () => {
	// Change the following line to `let typeFilter: "FOO" | "BAR" = "FOO";` and it will work
	let typeFilter = "FOO";

	if (Type[typeFilter] != Type.FOO) {
		return;
	}
};

export default Test;

Actual behavior:

test.ts:9:11 - error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.

9  if (Type[typeFilter] != Type.FOO) {
            ~~~~~~~~~~


Found 1 error.

Playground Link: Playground

Related Issues: Maybe #27297

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Reproduce el informe del ejemplo test.ts proporcionado ejecutando tsc --strict e inspeccionando el diagnóstico en Type[typeFilter]. Lee la ruta de comprobación de tipos de la búsqueda inversa de enum y el issue relacionado #27297 antes de decidir si debe cambiar el comportamiento o solo el mensaje; se considera terminado cuando el comportamiento previsto está establecido y cubierto por un caso de regresión.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
compilers
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.