npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eslint-plugin-no-object-comparison

v1.0.0

Published

ESLint rule to prevent comparing objects using comparison operators

Readme

eslint-plugin-no-object-comparison

An ESLint plugin that prevents unsafe comparisons in TypeScript. Uses the type system to detect when comparisons will fail silently.

Installation

pnpm add -D eslint-plugin-no-object-comparison

Requirements: ESLint >= 8, TypeScript >= 5, @typescript-eslint/parser >= 6

Important: This plugin requires typed linting to be enabled. You must configure parserOptions.project to point to your tsconfig.json.

Quick Start

// eslint.config.js
import tsParser from '@typescript-eslint/parser';
import noObjectComparison from 'eslint-plugin-no-object-comparison';

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: { project: './tsconfig.json' },
    },
  },
  noObjectComparison.configs.recommended,
];

Rules Overview

| Rule | Description | Recommended | |------|-------------|:-----------:| | object-equality | Prevent === on objects | error | | object-relational | Prevent < > on objects | error | | loose-type | Prevent comparisons with any | error | | nan-comparison | Prevent x === NaN | error | | self-comparison | Prevent x !== x | error | | floating-point-equality | Prevent 0.1 + 0.2 === 0.3 | error | | string-number-relational | Prevent '10' < '2' | error | | symbol-literal-comparison | Prevent Symbol() === Symbol() | error | | object-literal-switch-case | Prevent case {id:1}: | error | | boxed-primitive-comparison | Prevent new String() === new String() | error | | array-includes-object | Prevent arr.includes({}) | warn | | collection-reference-lookup | Prevent map.get({}) | warn | | collection-object-key | Prevent map.set(obj, val) | warn | | json-stringify-comparison | Prevent JSON.stringify() comparisons | warn |


Rules

object-equality

Prevents comparing objects with === or !==. Objects are compared by reference, not value.

// Bad - always false (different references)
if (user1 === user2) { }
if ({ id: 1 } === { id: 1 }) { }

// Good
if (user1.id === user2.id) { }

Full documentation


object-relational

Prevents relational comparisons (<, >, <=, >=) on objects without a valueOf method.

// Bad - objects coerce to '[object Object]'
if (user1 < user2) { }

// Good - compare primitive properties
if (user1.age < user2.age) { }

Full documentation


loose-type

Prevents comparisons involving any or unknown types, which bypass type safety.

// Bad - type system can't verify this
const data: any = fetchData();
if (data === user) { }

// Good - narrow the type first
if (isUser(data) && data.id === user.id) { }

Full documentation


nan-comparison

Prevents comparing with NaN using equality operators. NaN is not equal to anything, including itself.

// Bad - always false
if (x === NaN) { }
if (x !== NaN) { }  // always true

// Good
if (Number.isNaN(x)) { }

Full documentation


self-comparison

Prevents comparing a variable to itself, which is often an opaque NaN check or a typo.

// Bad - opaque NaN check
if (x !== x) { }

// Good - explicit NaN check
if (Number.isNaN(x)) { }

Full documentation


floating-point-equality

Prevents strict equality on floating-point arithmetic, which suffers from precision issues.

// Bad - false due to IEEE 754
if (0.1 + 0.2 === 0.3) { }

// Good - use epsilon comparison
if (Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) { }

Full documentation


string-number-relational

Prevents relational comparisons on numeric strings, which compare lexicographically.

// Bad - '9' > '10' is true (lexicographic)
if ('10' < '2') { }

// Good - convert to numbers
if (Number('10') < Number('2')) { }

Full documentation


symbol-literal-comparison

Prevents comparing Symbol() calls. Each call creates a unique symbol.

// Bad - always false (unique symbols)
if (Symbol('id') === Symbol('id')) { }

// Good - use Symbol.for() for shared symbols
if (Symbol.for('id') === Symbol.for('id')) { }

Full documentation


object-literal-switch-case

Prevents object literals in switch cases. Switch uses === which compares by reference.

// Bad - case never matches
switch (value) {
  case { type: 'admin' }: break;
}

// Good - compare primitives
switch (value.type) {
  case 'admin': break;
}

Full documentation


boxed-primitive-comparison

Prevents comparing boxed primitives (new String, new Number, new Boolean), which are objects.

// Bad - false (different objects)
new String('a') === new String('a')

// Good - use primitives
'a' === 'a'
String(x) === String(y)

Full documentation


array-includes-object

Prevents using includes(), indexOf(), lastIndexOf() with object literals or new expressions.

// Bad - never finds (different reference)
users.includes({ id: 1 })
arr.includes(new User())

// Good - use find/some
users.find(u => u.id === 1)
users.some(u => u.id === 1)

Full documentation


collection-reference-lookup

Prevents using object literals in Map/Set lookup methods (get, has, delete).

// Bad - never finds (different reference)
map.get({ id: 1 })
set.has({ id: 1 })

// Good - use stored reference
const key = { id: 1 };
map.set(key, 'value');
map.get(key);  // works

Full documentation


collection-object-key

Prevents using non-primitive keys in Map.set() and Set.add(). Object keys require keeping the exact reference.

// Bad - error-prone, must keep reference
map.set(user, 'data')
set.add(config)

// Good - use primitive keys
map.set(user.id, 'data')

// Good - use WeakMap for object keys
weakMap.set(user, 'data')

Full documentation


json-stringify-comparison

Prevents comparing JSON.stringify() results. Key order isn't guaranteed and some values are dropped.

// Bad - unreliable
JSON.stringify(a) === JSON.stringify(b)

// Good - use deep equality library
import { isEqual } from 'lodash';
isEqual(a, b)

Full documentation


Configs

| Rule | recommended | strict | |------|:-----------:|:------:| | object-equality | 🔴 | 🔴 | | object-relational | 🔴 | 🔴 | | loose-type | 🔴 | 🔴 | | nan-comparison | 🔴 | 🔴 | | self-comparison | 🔴 | 🔴 | | floating-point-equality | 🔴 | 🔴 | | string-number-relational | 🔴 | 🔴 | | symbol-literal-comparison | 🔴 | 🔴 | | object-literal-switch-case | 🔴 | 🔴 | | boxed-primitive-comparison | 🔴 | 🔴 | | array-includes-object | 🟡 | 🔴 | | collection-reference-lookup | 🟡 | 🔴 | | collection-object-key | 🟡 | 🔴 | | json-stringify-comparison | 🟡 | 🔴 |

🔴 error 🟡 warn

recommended

Core rules as errors, optional rules as warnings. Includes indirectReferences: 'warn' for lookup rules. Best for most projects.

noObjectComparison.configs.recommended

strict

All rules as errors, with indirectReferences: 'error' for lookup rules. For maximum safety.

noObjectComparison.configs.strict

Inline Suppression

// eslint-disable-next-line no-object-comparison/object-equality
if (obj1 === obj2) { }

License

MIT