L'opérateur '= = ' ne peut pas être appliqué aux types x et y dans Typescript 2

Tapuscrit Version: 2.0.2.0

Code Je sais que le code est un peu stupide, mais j'ai en fait ce genre de tests dans mon code (faire un visiteur d'expression) et je pense vraiment que ceux-ci devraient voler et compiler tout de suite.

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

Au lieu de cela, il se plaint que l'opérande equal ne peut pas être appliqué aux types 'true', 'false', ' 5 ' et '2'. Marquez qu'ils ne sont pas booléens ou numériques, ils sont en fait un type de 'true', 'false','5','2'. Je sais que les types 'string' et 'boolean' ne peuvent pas être comparés, mais bon, 5 est en fait un nombre, pas Tapez ' 5 ' ou est-ce que je me trompe?

Cela compile cependant.

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

Est-ce que je manque quelque chose, pourquoi ne sont pas 5 et 2 considérés comme type 'number' ?

Comportement Attendu: Devrait compiler

Comportement réel: Résultats dans une erreur de compilation disant 'Operand' = = 'ne peut pas être appliqué aux types' ' et ' '

Contexte je suis venu sur ce problèmes dans typescript définissant que cela devrait être comme ça, mais comment se fait-il? https://github.com/Microsoft/TypeScript/issues/6167

26
demandé sur Ahmad Baktash Hayeri 2016-08-31 10:19:44

4 réponses

Les types littéraux ont de nombreux avantages, car ils permettent au compilateur de rendre les types aussi étroits que possible. Votre cas d'utilisation est celui qui apparaît très rarement, mais vouloir que les types soient aussi étroits que possible imprègne toute la conception du langage. Alors oui, alors que cela rend votre vie plus difficile dans ce cas spécifique, cela a du sens dans la langue dans son ensemble. Les utilisateurs devraient souffrir d'une langue nettement pire, juste pour soutenir ce cas d'utilisation rare.

Malheureusement, vous devrez utiliser le typage explicite que vous vous suggérez dans le deuxième exemple. Je ne vois pas cela être corrigé, car la majorité des utilisateurs veut que la langue crie s'ils essaient de le faire. C'est probablement le signe d'un bogue dans une grande majorité des cas.

8
répondu Simon Meskens 2016-08-31 07:35:37

Pourquoi 5 et 2 ne sont-ils pas considérés comme du type 'number'

Ont le type littéral 5 et 2. par exemple

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

Je ne vois pas de cas d'utilisation réel pour vouloir que ce ne soit pas une erreur. C'est juste le compilateur qui essaie de vous aider. N'hésitez pas à créer un problème si vous voyez une motivation suffisante

10
répondu basarat 2018-06-26 15:06:57

En tant que développeur Erlang, j'avais l'habitude de voir ce genre d'erreurs dans Erlang, mais je ne savais pas ce que cela signifiait dans TypeScript, voici un exemple qui vous aidera à comprendre le problème:

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');
}

Il ne compilera pas avec erreur:

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

Tout d'Abord, voici solution

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

Maintenant l'explication:

Comme ce code est très simple et peut être compris au moment de la compilation, TypeScript sait qu'il n'y a pas d'endroit dans le code où {[5] } pourrait devenir "no", donc juste vous dit (bien que sous une forme assez cryptique) que la réponse n'est toujours pas "non", donc il n'y a littéralement aucune raison de vérifier si c'est le cas. Mais (comme dans Erlang) cela peut arriver pour une raison assez évidente, lorsque vous avez par exemple décidé de commenter du code pour le débogage qui faisait que answer devenait "no". Maintenant, si nous utilisons let answer = "yes" as "yes" | "no" | "maybe"; ou let answer = <("yes" | "no" | "maybe")>"yes";, cela fera penser à TypeScript que "oui" peut être "non" même si vous ne pouvez pas le voir dans le code. Donc, pour le cas de code temporairement supprimé, il y a second solution :

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

Même si cette condition ne sera jamais vraie, elle est assez "complexe" pour que le compilateur TypeScript pense que cela peut être vrai. Mon approche Erlang consiste à utiliser when X and not X qui serait if (x && !x) { mais au moins dans 2.4, Vous pouvez simplement utiliser des expressions numériques.

Mais à un moment donné, le compilateur pourrait juste avoir raison et alors la solution est de supprimer check for "no" :)

Donc, en revenant à la question de L'OP, pour compiler votre code, vous devez changer il à:

var a = false;
var b = false;

Si le compilateur le sait, vous le saviez probablement aussi.

4
répondu JLarky 2017-08-30 00:31:34

Fait face au même problème dans un scénario que le suivant:

let a: string;

a === 'some-value1' && a === 'some-value2';  // <==

La deuxième ligne produit la même erreur et peut-être parce que Typescript est smart suffisant pour savoir qu'un type de chaîne à un moment donné ne peut pas contenir deux (ou plus) littéraux de chaîne différents.

L'approche correcte de l'expression ci-dessus serait d'utiliser OU dans l'expression:

a === 'some-value1' || a === 'some-value2';  // works fine :)
0
répondu Ahmad Baktash Hayeri 2018-07-25 04:24:56