运算符“==”不能应用于 Typescript 2 中的类型 x 和 y

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39243143/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:18:23  来源:igfitidea点击:

Operator '==' cannot be applied to types x and y in Typescript 2

typescripttype-conversiontypescript2.0

提问by Lostfields

TypeScript Version:2.0.2.0

打字稿版本:2.0.2.0

CodeI know the code is a bit stupid, but I actually have these kind of tests in my code (making an expression visitor) and I really think these should fly and compile right away.

代码我知道代码有点愚蠢,但实际上我的代码中有这些测试(创建表达式访问者),我真的认为这些测试应该立即运行并编译。

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

Instead it complains that operand equal cannot be applied to types 'true', 'false', '5' and '2'. Mark that they are not boolean or number, they are actually a types of 'true','false','5','2'. I know that types 'string' and 'boolean' cannot be compared, but hey, 5 is actually a number, not type '5' or am I mistaken?

相反,它抱怨操作数相等不能应用于类型“真”、“假”、“5”和“2”。标记它们不是布尔值或数字,它们实际上是“真”、“假”、“5”、“2”的类型。我知道类型 'string' 和 'boolean' 不能比较,但是嘿,5 实际上是一个数字,而不是类型 '5' 还是我弄错了?

This compiles though.

这虽然编译。

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

Am I missing something, why arent't 5 and 2 considered as type 'number' ?

我错过了什么,为什么 5 和 2 不被视为“数字”类型?

Expected behavior:Should compile

预期行为:应该编译

Actual behavior:Results in a compile error saying 'Operand '==' cannot be applied to types '<first argument>' and '<second argument>'

实际行为:导致编译错误,提示“操作数‘==’不能应用于类型‘<第一个参数>’和‘<第二个参数>’

BackgroundI came over this issues in typescript defining that it should be like this, but how come? https://github.com/Microsoft/TypeScript/issues/6167

背景我在打字稿中遇到了这个问题,定义它应该是这样的,但怎么会呢? https://github.com/Microsoft/TypeScript/issues/6167

采纳答案by Simon Meskens

Literal types have many advantages, as it lets the compiler make types as narrow as possible. Your use case is one that comes up very rarely, but wanting types to be as narrow as possible permeates the entire design of the language. So yes, while it makes your life harder in this one specific case, it makes sense in the language as a whole. Users would have to suffer a significantly worse language, just to support this one rare use case.

文字类型有许多优点,因为它可以让编译器使类型尽可能窄。您的用例很少出现,但希望类型尽可能窄,这贯穿了语言的整个设计。所以是的,虽然在这种特定情况下它会让你的生活变得更难,但它在整个语言中是有意义的。用户将不得不忍受一种更糟糕的语言,只是为了支持这个罕见的用例。

Unfortunately, you will have to use the explicit typing you suggest yourself in the second example. I don't see this ever being fixed, because the majority of users wantsthe language to yell if they try to do this. It's probably the sign of a bug in a large majority of cases.

不幸的是,您将不得不使用您在第二个示例中建议的显式类型。我不认为这会被修复,因为大多数用户希望如果他们尝试这样做,语言就会大喊大叫。在大多数情况下,这可能是错误的迹象。

回答by basarat

why aren't 5 and 2 considered as type 'number'

为什么 5 和 2 不被视为“数字”类型

The have the literal type 5and 2. e.g.

具有文字类型52. 例如

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

I don't see an actual use case for wanting it not to be an error. This is just the compiler trying to help you. Feel free to create an issue if you see sufficient motivation

我没有看到希望它不是错误的实际用例。这只是试图帮助您的编译器。如果您看到足够的动机,请随意创建一个问题

回答by JLarky

As Erlang developer I used to see this kind of errors in Erlang, but was unsure what it means in TypeScript, here's example that will help you understand the problem:

作为 Erlang 开发人员,我曾经在 Erlang 中看到过这种错误,但不确定它在 TypeScript 中的含义,以下示例将帮助您理解问题:

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

It will not compile with error:

它不会编译出错:

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

First, here's the solution

首先,这是解决方案

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

Now the explanation:

现在解释:

Since this code is very simple and could be understood at compile time, TypeScript knows that there's no where in code where answercould become "no", so it just says to you (although in quite cryptic form) that answer is always not "no", so there's literally no reason to ever check if it is. But (as in Erlang) this can happen for quite obvious reason, when you for example decided to comment out some code for debug that was making answerto become "no". Now if we use let answer = "yes" as "yes" | "no" | "maybe";or let answer = <("yes" | "no" | "maybe")>"yes";it will make TypeScript think that "yes" can be "no" even if you can't see it in code. So for case of temporarily removed code there's second solution:

由于这段代码非常简单并且可以在编译时理解,TypeScript 知道代码中没有哪里answer可以变成"no",所以它只是告诉你(虽然以相当神秘的形式)答案总是不是“不”,所以有从字面上看,没有理由检查它是否是。但是(如在 Erlang 中)这可能出于非常明显的原因而发生,例如,当您决定注释掉一些正在answer成为"no". 现在,如果我们使用let answer = "yes" as "yes" | "no" | "maybe";orlet answer = <("yes" | "no" | "maybe")>"yes";它会使 TypeScript 认为“是”可以是“否”,即使您在代码中看不到它。因此,对于临时删除代码的情况,有第二种解决方案

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

Even though this condition will never be true it is "complex" enough for TypeScript compiler to think that it can be true. My Erlang approach is to use when X and not Xwhich would be if (x && !x) {but at least in 2.4 you can just use number expressions.

尽管这个条件永远不会成立,但它“复杂”到足以让 TypeScript 编译器认为它可能是真的。我的 Erlang 方法是使用when X and not Xwhich ,if (x && !x) {但至少在 2.4 中你可以只使用数字表达式。

But at some point compiler might just be right and then solutionis to remove check for "no":)

但在某些时候编译器可能是正确的,然后解决方案是删除检查"no":)

So returning that back to the OP's question, to make your code compile you need to change it to:

因此,回到 OP 的问题,要使您的代码编译,您需要将其更改为:

var a = false;
var b = false;

If compiler knows that, you probably knew that too.

如果编译器知道这一点,您可能也知道这一点。

回答by Ahmad Baktash Hayeri

Faced the same issue in a scenario as the following:

在以下场景中遇到了同样的问题:

let a: string;

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

The second line produces the same error and maybe because Typescript is smartenough to know that a string type at a given moment cannot contain two (or more) different string literals.

第二行产生相同的错误,可能是因为 Typescript足够聪明,知道在给定时刻的字符串类型不能包含两个(或更多)不同的字符串文字。

The correct approach for the above expression would be to use OR in the expression:

上述表达式的正确方法是在表达式中使用 OR:

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