javascript 为什么在TypeScript中使用三重等于(===)?

qeeaahzv  于 2023-02-15  发布在  Java
关注(0)|答案(4)|浏览(198)

在JavaScript中,通常认为使用===而不是==是最佳实践,原因是显而易见的。
在TypeScript中,哪一个是首选的?甚至有一个比另一个更好吗?
恕我直言,在TypeScript中使用===没有意义,因为比较只适用于相同的类型,因此您不会像普通JavaScript中那样遇到强制游戏(或多或少有点滑稽)。如果您暂时不考虑与JavaScript的兼容性,TypeScript甚至可以摆脱===,不是吗?

dm7nw8vv

dm7nw8vv1#

简短版本

==可能会进行意外的类型转换,在Javascript中1=="1"true===运算符可避免此问题。将不同类型与===进行比较时始终为false
当你用==比较不同的类型时,typescript编译器会发出一个错误消息。这消除了在Javascript中使用==时可能发生的意外类型转换。
在这种情况下,有效的Javascript会导致typescript编译器中出现错误消息。所有有效的Javascript都是有效的Typescript的想法是一个常见的误解。这是完全不正确的。

较长版本:我认为公认的答案是误导的。Typescript实际上确实修复了== vs ===(至少尽可能地)。

在Javascript中有两个比较运算符:

  • ==:当比较基元值(如数字和字符串)时,此运算符将在进行比较之前应用类型转换。1 == "1"计算为true
  • ===:此运算符不进行类型转换。如果类型不匹配,它将始终返回false

此外,两个运算符将根据其引用比较引用类型。两个单独的对象永远不会被视为彼此相等,即使它们存储相同的值:

let a = {val:1};
let b = {val:1};
c = a;

a==b; // false
a===b; // false
a==c; //true
a===c; //true

因此,在Javascript比较中有两个常见的错误来源:
1.用==比较不同的类型可能导致意外的类型转换。
1.比较对象和数组是基于引用而不是存储在其中的值。
正如已有的答案所说,Typescript被设计为Javascript的超集,因此它不会改变这些比较运算符的行为。如果你在Typescript中编写==,你会得到类型转换。
那么这个问题是如何解决的呢?用编译器。如果你真的写了一段代码来比较不兼容的类型和==,那就是一个编译器错误。试着编译下面的例子:

let str = "1";
let num = 1;

console.log(str == num);

编译器将告诉您:

comparisons.ts:4:13 - error TS2367: This condition will always return 'false' since the types 'string' and 'number' have no overlap.

4 console.log(str == num);
              ~~~~~~~~~~

Found 1 error.

一个常见的误解是任何有效的Javascript也是有效的Typescript。这是不正确的,上面的代码是一个例子,其中typescript编译器将抱怨有效的Javascript。
这将修复两个错误来源中的第一个:意外的类型转换。它不处理第二个错误源:基于引用的比较。据我所知,当你想基于对象存储的值进行比较时,你根本不能使用这些操作符。你必须实现你自己的equals()方法。
还有,你可能已经注意到编译器错误是错误的,比较不会总是求值为false,我认为这是typescript中的bug,有filed an issue

ni65a41a

ni65a41a2#

假设您正在从头开始设计TypeScript,本质上,您正在尝试优化以使更安全的代码更易于编写(TypeScript设计目标1),但有一些注意事项会阻止您做所有您想做的事情。

JavaScript兼容性(TypeScript设计目标7)

JavaScript应该是未做任何更改的有效 typescript 。
CoffeeScript对此不做任何保证,所以它可以将所有==的示例转换为===,并简单地告诉用户 * 不要依赖==的行为 *。TypeScript无法在不破坏所有依赖其行为的JavaScript代码的情况下重新定义==(尽管这对3有很坏的影响)。
这也意味着TypeScript不能改变===的功能,例如,在编译时检查两个操作数的类型,并拒绝比较不同类型变量的程序。
此外,兼容性不限于简单的JavaScript程序;破坏兼容性也会影响JavaScript程序员,因为破坏了他们对=====之间差异的假设。
引入可能会让用户吃惊的行为,而不是适当考虑其他常用语言所采用的模式。

JavaScript作为编译目标(TypeScript设计目标4)

所有的TypeScript都必须可以用JavaScript来表示。此外,如果可能的话,它应该是惯用的JavaScript。
实际上,TypeScript编译器可以使用返回布尔值的方法来进行所有的比较,完全不用=====,这对用户来说可能更安全:在每个TypeScript类型上定义一个类型安全的等式方法(很像C++ operator==,只是没有重载)。
因此有一个变通方法(对于比较类的用户)。unknownany变量可以在使用类型安全的相等方法之前缩小其类型。
∮你喜欢哪一个∮
在JavaScript中的任何地方都可以使用===。这样做的好处是避免了==常见的陷阱,并且不需要维护额外的方法。TypeScript编译器的输出将接近于惯用的JavaScript。**使用==与JavaScript有着非常相似的陷阱,特别是当您使用any[]、或{}。**例外情况是,如果库代码不一致,使用== null检查nullundefined可以保存麻烦。
引用相等的方法(类似于类的===行为)可能会与深度/值递归相等检查混淆。此外,===在TypeScript中广泛使用,使代码符合约定通常比任何一点类型安全都重要。

qvsjd97n

qvsjd97n3#

你的直觉是正确的。在TypeScript中使用===来模拟相等性检查是没有意义的。TS编译到JS“所以你应该使用JS”中更好的参数是无效的。为什么?因为Typescript确保比较运算符的两个操作数(s)具有相同的类型。当两个操作数具有相同的类型时,=====的行为相同。“相同”是指100%相同,而不仅仅是“相似”。因此没有 * 更正确 *或 * 不太正确 * 的版本,当两者在JavaScript中的行为完全相同时。
我猜这里的其他评论者只是在寻找方法来保持他们使用===的习惯,或者换句话说是合理化。不幸的是,纯逻辑告诉我们并非如此:用===替换==是没有意义的,除非您打算手动修改生成的JS代码,而这种情况可能永远不会发生。
我使用===专门用于身份检查(当你比较x和x -相同的变量时,在与记忆相关的库代码中有时是必要的),而我的与eqeq运算符相关的错误计数器显示0。
示例:

const s : string = "s"
const n : number = 1
console.log(s == n)

TS2367: This condition will always return 'false' since the types 'string' 
and 'number' have no overlap
q8l4jmvw

q8l4jmvw4#

我的意见是应该始终使用===
第一条推理:TypeScript不会将==更改为===。有一些TypeScript转换器只会剥离类型。因此,如果由于某种原因忘记对程序进行类型检查,或者如果您(或您代码的未来维护人员)使用类型转换来覆盖类型安全,则到处使用===会导致代码更健壮。不应该发生这种情况,但许多事情都不应该发生。
第二条推理:null == undefined。TypeScript也是如此。我认为如果编写if (x == null),代码的可读性会降低,因为它也暗示了对undefined的检查,并且隐式代码的可读性比显式if (x === null || x === undefined)低。如果不是故意这样做,也可能会出现细微的bug。
除了审美偏好,我看不出在任何地方无条件使用===有什么问题。

相关问题