Skip to content

unnecessaryComparisons

Reports comparisons that are always true, always false, or can be simplified.

✅ This rule is included in the ts logical and logicalStrict presets.

This rule detects comparison patterns that are logically unnecessary, impossible, or can be simplified. Such patterns often indicate logic errors, copy-paste mistakes, or overly complex code that should be refactored.

The rule covers several categories of problematic comparisons:

  1. Self-comparisons: Comparing a value to itself (e.g., x === x)
  2. Impossible ranges: Range checks that can never be satisfied (e.g., x <= 400 && x > 500)
  3. Redundant double comparisons: OR patterns that can be simplified (e.g., x === y || x < y can become x <= y)
  4. Ineffective checks: Redundant bounds in AND chains (e.g., x < 200 && x <= 299 where the second check is always true when the first is)
AE53 (valuAE=<==sp ansty="le--0:#D6DEEB;--1:#403F">53 value)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// Always tr5<3}d ivclassNa="meco"><}d>AE53 (valuA53 value)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// Always fal5<3}d ivclassNa="meco"><}d>
443F53 (va44A3F53 otherValude6376// Compare different va3<}di vdivclass="Nameexpressive-">6376// Use Number.isNaN() for NaN ch443F53 (Nu4<4AE. spans="tyle--0:#82AAFF;--1:#3B">61B0i3F53(value<)) {divclass="Nameec-">de6376//< .. .divclass="Nameec-">3<..>
76// Can never be true: no value is both <= 400 AND > 5<00d ivclassNa="meec-li">AE53 (AE<<=sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#F78C6C;--1:#AA09">824<00sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#C792EA;--1:#8844">AE<&&sp ansty="le--0:#D6DEEB;--1:#403F">53 Asp ansty="le--0:#D6DEEB;--1:#403F">5sp><3 sp ansty="le--0:#F78C6C;--1:#AA09">825<00sp ansty="le--0:#D6DEEB;--1:#403F">53)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// Unreachable co5<3}d ivclassNa="meco"><}d>76// Impossible boundary conditiAE53 (A5<3 sp ansty="le--0:#F78C6C;--1:#AA09">8<25sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#C792EA;--1:#8844">AE<&&sp ansty="le--0:#D6DEEB;--1:#403F">53 AE<>=sp ansty="le--0:#D6DEEB;--1:#403F">5=sp><3 sp ansty="le--0:#F78C6C;--1:#AA09">8<25sp ansty="le--0:#D6DEEB;--1:#403F">53)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// Never execut5<3}d ivclassNa="meco"><}d>
6376// Valid range: x is between 400 and< 50 0divclass="Nameec-">443F53< (x spans="tyle--0:#C792EA;--1:#88">44= spans="tyle--0:#D6DEEB;--1:#40">3=>098<2400 spans="tyle--0:#D6DEEB;--1:#40">3443F5<3 x spans="tyle--0:#C792EA;--1:#88">443098<2500 spans="tyle--0:#D6DEEB;--1:#40">3F5<3) {divclass="Nameec-">de6376//< .. .divclass="Nameec-">3<..><}di vdivclass="Nameexpressive-">6376// Valid narrow r443F53< (x spans="tyle--0:#C792EA;--1:#88">4<4AE> spans="tyle--0:#D6DEEB;--1:#40">3>0<9825 spans="tyle--0:#D6DEEB;--1:#40">3443F5<3 x spans="tyle--0:#C792EA;--1:#88">4<4AE< spans="tyle--0:#D6DEEB;--1:#40">309<8210 spans="tyle--0:#D6DEEB;--1:#40">3F5<3) {divclass="Nameec-">de6376//< .. .divclass="Nameec-">3<..>
76// Can be simplified to: x <=< yd ivclassNa="meec-li">AE53 (AE=<==sp ansty="le--0:#D6DEEB;--1:#403F">53 AE<||sp ansty="le--0:#D6DEEB;--1:#403F">53 A53 y)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// .<..d ivclassNa="meec-li">5<3}d ivclassNa="meco"><}d>76// Can be simplified to: x >=< yd ivclassNa="meec-li">AE53 (AE=<==sp ansty="le--0:#D6DEEB;--1:#403F">53 AE<||sp ansty="le--0:#D6DEEB;--1:#403F">53 Asp ansty="le--0:#D6DEEB;--1:#403F">53 y)sp>< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// .<..d ivclassNa="meec-li">5<3}d ivclassNa="meco"><}d>
6376// Use the simpler combined oper443F53< (x spans="tyle--0:#C792EA;--1:#88">443F53 de6376//< .. .divclass="Nameec-">3<..><}di vdivclass="Nameexpressive-">443F53< (x spans="tyle--0:#C792EA;--1:#88">44= spans="tyle--0:#D6DEEB;--1:#40">3F53 =>de6376//< .. .divclass="Nameec-">3<..>
76// x <= 299 is redundant when x < 200 is already checkAE53 (A5<3 sp ansty="le--0:#F78C6C;--1:#AA09">822<00sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#C792EA;--1:#8844">AE<&&sp ansty="le--0:#D6DEEB;--1:#403F">53 AE<<=sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#F78C6C;--1:#AA09">822<99sp ansty="le--0:#D6DEEB;--1:#403F">53)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// The second check adds nothi5<3}d ivclassNa="meco"><}d>76// x >= 50 is redundant when x > 100 is already checkAE53 (Asp ansty="le--0:#D6DEEB;--1:#403F">5sp><3 sp ansty="le--0:#F78C6C;--1:#AA09">821<00sp ansty="le--0:#D6DEEB;--1:#403F">5<3 sp ansty="le--0:#C792EA;--1:#8844">AE<&&sp ansty="le--0:#D6DEEB;--1:#403F">53 AE<>=sp ansty="le--0:#D6DEEB;--1:#403F">5=sp><3 sp ansty="le--0:#F78C6C;--1:#AA09">82<50sp ansty="le--0:#D6DEEB;--1:#403F">53)< {d ivclassNa="meec-li">nt< sp ansty="le--0:#919F9F;--1:#5D63">76// .<..d ivclassNa="meec-li">5<3}d ivclassNa="meco"><}d>
6376// Just use the stronger constr443F53< (x spans="tyle--0:#C792EA;--1:#88">4<4AE< spans="tyle--0:#D6DEEB;--1:#40">3098<2200 spans="tyle--0:#D6DEEB;--1:#40">3F5<3) {divclass="Nameec-">de6376//< .. .divclass="Nameec-">3<..><}di vdivclass="Nameexpressive-">6376// Or use both bounds when they're actually ne443F53< (x spans="tyle--0:#C792EA;--1:#88">4<4AE> spans="tyle--0:#D6DEEB;--1:#40">3>098<2100 spans="tyle--0:#D6DEEB;--1:#40">3443F5<3 x spans="tyle--0:#C792EA;--1:#88">4<4AE< spans="tyle--0:#D6DEEB;--1:#40">3098<2200 spans="tyle--0:#D6DEEB;--1:#40">3F5<3) {divclass="Nameec-">de6376// Valid range c3

This rule is not configurable.

If your codebase relies on dynamic getters or other side effects that could make seemingly-identical expressions return different values, you might want to disable this rule for those specific cases.