typescript type-conversion typescript2.0

El operador ''=='' no se puede aplicar a los tipos x e y en Typescript 2



type-conversion typescript2.0 (4)

Versión de TypeScript: 2.0.2.0

Código Sé que el código es un poco estúpido, pero en realidad tengo este tipo de pruebas en mi código (lo que hace que la expresión sea un visitante) y realmente creo que deberían volar y compilarse de inmediato.

var a: boolean = (true == false); var b: boolean = (5 == 2);

En su lugar, se queja de que el operando igual no se puede aplicar a los tipos ''true'', ''false'', ''5'' and ''2''. Marque que no son booleanos ni numéricos, en realidad son tipos de ''verdadero'', ''falso'', ''5'', ''2''. Sé que los tipos ''string'' y ''boolean'' no se pueden comparar, pero hey, 5 es en realidad un número, no el tipo ''5'' o ¿me equivoco?

Esto compila sin embargo.

let x = 2; var a: boolean = 5 == x; var b: boolean = <number>5 == <number>2;

¿Me estoy perdiendo algo, por qué no se consideran 5 y 2 como tipo ''número''?

Comportamiento esperado: debe compilar

Comportamiento real: los resultados en un error de compilación que dice ''Operando'' == ''no se pueden aplicar a los tipos'' <primer argumento> ''y'' <segundo argumento> ''

Antecedentes Me encontré con estos problemas en escritura de caracteres, definiendo que debería ser así, pero ¿cómo es posible? https://github.com/Microsoft/TypeScript/issues/6167


¿Por qué no se consideran 5 y 2 como tipo ''número''?

Tienen el tipo literal 5 y 2 . p.ej

var x: 5; // can only ever be assigned to 5 x = 5; // okay x = 2; // Error

No veo un caso de uso real para querer que no sea un error. Esto es solo el compilador tratando de ayudarte. Siéntase libre de crear un problema si ve suficiente motivación.


Como desarrollador de Erlang, solía ver este tipo de errores en Erlang, pero no estaba seguro de lo que significa en TypeScript, aquí hay un ejemplo que te ayudará a entender el problema:

let answer: "yes" | "no" | "maybe" = "yes"; if (Math.random() > 0.5) { answer = "maybe"; } if (answer === "yes") { console.log(''yes''); } if (answer === "no") { console.log(''no''); }

No se compilará con error:

error TS2365: Operator ''==='' cannot be applied to types ''"yes" | "maybe"'' and ''"no"''.

Primero, aquí está la solución.

let answer = "yes" as "yes" | "no" | "maybe";

Ahora la explicación:

Dado que este código es muy simple y podría entenderse en tiempo de compilación, TypeScript sabe que no hay ningún lugar en el que el código de answer se convierta en "no" , por lo que simplemente le dice a usted (aunque en forma bastante críptica) que la respuesta siempre es "no" ", así que, literalmente, no hay razón para comprobar si lo es. Pero (como en Erlang) esto puede suceder por una razón bastante obvia, cuando, por ejemplo, decidió comentar algunos códigos de depuración que answer para convertirse en "no" . Ahora si usamos let answer = "yes" as "yes" | "no" | "maybe"; let answer = "yes" as "yes" | "no" | "maybe"; o let answer = <("yes" | "no" | "maybe")>"yes"; hará que TypeScript piense que "sí" puede ser "no" incluso si no puede verlo en el código. Así que para el caso de código eliminado temporalmente hay una segunda solución :

if (0) { answer = "no"; }

Aunque esta condición nunca será cierta, es lo suficientemente complejo como para que el compilador de TypeScript piense que puede ser cierto. Mi enfoque de Erlang es usar when X and not X que sería if (x && !x) { pero al menos en 2.4 puede usar expresiones numéricas.

Pero en algún punto, el compilador podría tener razón y la solución es eliminar la casilla de verificación de "no" :)

Entonces, volviendo a la pregunta del OP, para hacer que su código se compile, necesita cambiarlo a:

var a = false; var b = false;

Si el compilador sabe eso, probablemente también lo sabías.


Enfrentó el mismo problema en un escenario como el siguiente:

let a: string; a === ''some-value1'' && a === ''some-value2''; // <==

La segunda línea produce el mismo error y quizás porque Typescript es lo suficientemente inteligente como para saber que un tipo de cadena en un momento dado no puede contener dos (o más) literales de cadena diferentes.

El enfoque correcto para la expresión anterior sería usar OR en la expresión:

a === ''some-value1'' || a === ''some-value2''; // works fine :)


Los tipos literales tienen muchas ventajas, ya que permiten al compilador hacer tipos lo más estrechos posible. Su caso de uso es uno que aparece muy raramente, pero el hecho de que los tipos sean lo más estrechos posible impregna todo el diseño del lenguaje. Así que sí, aunque hace su vida más difícil en este caso específico, tiene sentido en el lenguaje en su conjunto. Los usuarios tendrían que sufrir un lenguaje significativamente peor, solo para admitir este caso de uso excepcional.

Desafortunadamente, tendrá que usar la escritura explícita que sugiere en el segundo ejemplo. No veo que esto se solucione nunca, porque la mayoría de los usuarios quieren que el idioma grite si intentan hacerlo. Es probable que sea el signo de un error en la gran mayoría de los casos.