CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fast-equals

A blazing fast equality comparison library for JavaScript and TypeScript

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Fast Equals

Fast Equals is a blazing fast equality comparison library for JavaScript and TypeScript that provides both deep and shallow equality comparisons. It handles complex data types including NaN, Date objects, RegExp objects, Map/Set collections, Promise objects, and React elements with specialized high-performance algorithms and optional circular reference support.

Package Information

  • Package Name: fast-equals
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install fast-equals

Core Imports

import { deepEqual, shallowEqual, circularDeepEqual, circularShallowEqual, sameValueZeroEqual, createCustomEqual, createCustomCircularEqual } from "fast-equals";

For CommonJS:

const { deepEqual, shallowEqual, circularDeepEqual, circularShallowEqual, sameValueZeroEqual, createCustomEqual, createCustomCircularEqual } = require("fast-equals");

Basic Usage

import { deepEqual, shallowEqual } from "fast-equals";

// Deep equality comparison
const objA = { foo: { bar: "baz" } };
const objB = { foo: { bar: "baz" } };

console.log(objA === objB); // false
console.log(deepEqual(objA, objB)); // true

// Shallow equality comparison
const nestedObject = { bar: "baz" };
const shallowA = { foo: nestedObject };
const shallowB = { foo: nestedObject };
const shallowC = { foo: { bar: "baz" } };

console.log(shallowEqual(shallowA, shallowB)); // true (same reference)
console.log(shallowEqual(shallowA, shallowC)); // false (different references)

Architecture

Fast Equals is built around several key components:

  • Core Comparators: Optimized functions for deep and shallow equality with different performance characteristics
  • Circular Support: Specialized variants that handle circular references using WeakMap-based caching
  • Type-Specific Handlers: Dedicated comparison logic for different data types (arrays, objects, dates, maps, sets, regexps)
  • Custom Comparator Factory: Extensible system for creating custom equality comparators with user-defined behavior
  • SameValueZero Compliance: Handles NaN equality and other edge cases according to ECMAScript specifications

Capabilities

Deep Equality Comparison

Performs comprehensive deep equality comparison on objects with full type support and optimized performance.

/**
 * Whether the items passed are deeply-equal in value.
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns Boolean indicating deep equality
 */
function deepEqual<A, B>(a: A, b: B): boolean;

Usage Examples:

import { deepEqual } from "fast-equals";

// Primitive comparison
deepEqual(42, 42); // true
deepEqual("hello", "hello"); // true
deepEqual(NaN, NaN); // true

// Object comparison
deepEqual({ a: 1, b: { c: 3 } }, { a: 1, b: { c: 3 } }); // true
deepEqual([1, [2, 3]], [1, [2, 3]]); // true

// Date comparison
deepEqual(new Date("2023-01-01"), new Date("2023-01-01")); // true

// Map comparison (keys and values are compared deeply)
const map1 = new Map([[{ key: "value" }, "data"]]);
const map2 = new Map([[{ key: "value" }, "data"]]);
deepEqual(map1, map2); // true

// Set comparison
deepEqual(new Set([1, 2, 3]), new Set([3, 2, 1])); // true

Shallow Equality Comparison

Performs shallow equality comparison where nested objects are compared by reference only.

/**
 * Whether the items passed are shallowly-equal in value.
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns Boolean indicating shallow equality
 */
function shallowEqual<A, B>(a: A, b: B): boolean;

Usage Examples:

import { shallowEqual } from "fast-equals";

const shared = { nested: "value" };
const obj1 = { a: 1, b: shared };
const obj2 = { a: 1, b: shared };
const obj3 = { a: 1, b: { nested: "value" } };

shallowEqual(obj1, obj2); // true (same references)
shallowEqual(obj1, obj3); // false (different references for b)

// Array shallow comparison
shallowEqual([1, 2, shared], [1, 2, shared]); // true
shallowEqual([1, 2, { x: 1 }], [1, 2, { x: 1 }]); // false

Circular Reference Support

Specialized equality comparisons that handle circular references safely using WeakMap-based caching.

/**
 * Whether the items passed are deeply-equal in value, including circular references.
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns Boolean indicating deep equality with circular support
 */
function circularDeepEqual<A, B>(a: A, b: B): boolean;

/**
 * Whether the items passed are shallowly-equal in value, including circular references.
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns Boolean indicating shallow equality with circular support
 */
function circularShallowEqual<A, B>(a: A, b: B): boolean;

Usage Examples:

import { circularDeepEqual, circularShallowEqual } from "fast-equals";

// Circular object example
function createCircular(value: string) {
  const obj: any = {
    me: {
      deeply: {
        nested: {
          reference: null, // Will be set to obj
        },
      },
    },
    value,
  };
  obj.me.deeply.nested.reference = obj;
  return obj;
}

const circular1 = createCircular("foo");
const circular2 = createCircular("foo");
const circular3 = createCircular("bar");

circularDeepEqual(circular1, circular2); // true
circularDeepEqual(circular1, circular3); // false

// Circular array example
const array: any[] = ["foo"];
array.push(array);

circularShallowEqual(array, ["foo", array]); // true

SameValueZero Equality

Performs SameValueZero comparison according to ECMAScript specification.

/**
 * Whether the values passed are strictly equal or both NaN.
 * @param a - First value to compare
 * @param b - Second value to compare
 * @returns Boolean indicating SameValueZero equality
 */
function sameValueZeroEqual<A, B>(a: A, b: B): boolean;

Usage Examples:

import { sameValueZeroEqual } from "fast-equals";

sameValueZeroEqual(1, 1); // true
sameValueZeroEqual(NaN, NaN); // true
sameValueZeroEqual(0, -0); // true
sameValueZeroEqual(1, "1"); // false
sameValueZeroEqual({}, {}); // false (different object references)

Custom Comparator Creation

Factory functions for creating custom equality comparators with user-defined behavior for specific use cases.

/**
 * Create a custom equality comparison method.
 * @param getComparatorOptions - Function that receives default options and returns custom overrides
 * @returns Custom equality comparator function
 */
function createCustomEqual<Meta = undefined>(
  getComparatorOptions: GetComparatorOptions<Meta>
): EqualityComparator<Meta>;

/**
 * Create a custom equality comparison method that handles circular references.
 * @param getComparatorOptions - Function that receives default options and returns custom overrides
 * @returns Custom circular equality comparator function
 */
function createCustomCircularEqual<Meta extends BaseCircularMeta = WeakMap<any, any>>(
  getComparatorOptions: GetComparatorOptions<Meta>
): EqualityComparator<Meta>;

Usage Examples:

import { createCustomEqual, createCustomCircularEqual } from "fast-equals";

// Create custom comparator that ignores RegExp flags
const customEqual = createCustomEqual((defaultOptions) => ({
  areRegExpsEqual: (a, b) => a.source === b.source, // Ignore flags
}));

const regex1 = /test/gi;
const regex2 = /test/m;
customEqual(regex1, regex2); // true (same source, flags ignored)

// Create custom circular comparator for legacy environments
const customCircularEqual = createCustomCircularEqual((defaultOptions) => ({
  // Use custom cache implementation instead of WeakMap
  createIsNestedEqual: (comparator) => {
    const cache = new Map(); // Fallback for environments without WeakMap
    return (a, b, indexOrKeyA, indexOrKeyB, parentA, parentB, meta) => {
      // Custom circular detection logic
      return comparator(a, b, meta);
    };
  },
}));

Types

/**
 * Base interface for circular reference metadata
 */
interface BaseCircularMeta extends Pick<WeakMap<any, any>, 'delete' | 'get'> {
  set(key: object, value: any): any;
}

/**
 * Configuration options for comparator creators
 */
interface CreateComparatorCreatorOptions<Meta> {
  areArraysEqual: TypeEqualityComparator<any, Meta>;
  areDatesEqual: TypeEqualityComparator<any, Meta>;
  areMapsEqual: TypeEqualityComparator<any, Meta>;
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
  areSetsEqual: TypeEqualityComparator<any, Meta>;
  createIsNestedEqual: EqualityComparatorCreator<Meta>;
}

/**
 * Function type for getting comparator options
 */
type GetComparatorOptions<Meta> = (
  defaultOptions: CreateComparatorCreatorOptions<Meta>
) => Partial<CreateComparatorCreatorOptions<Meta>>;

/**
 * Internal equality comparator used by the system
 */
type InternalEqualityComparator<Meta> = (
  a: any,
  b: any,
  indexOrKeyA: any,
  indexOrKeyB: any,
  parentA: any,
  parentB: any,
  meta: Meta
) => boolean;

/**
 * Conditional type for equality comparators based on Meta parameter
 */
type EqualityComparator<Meta> = Meta extends undefined
  ? <A, B>(a: A, b: B, meta?: Meta) => boolean
  : <A, B>(a: A, b: B, meta: Meta) => boolean;

/**
 * Creates internal equality comparator from external one
 */
type EqualityComparatorCreator<Meta> = (
  fn: EqualityComparator<Meta>
) => InternalEqualityComparator<Meta>;

/**
 * Simple equality comparator without metadata
 */
type NativeEqualityComparator = <A, B>(a: A, b: B) => boolean;

/**
 * Typed equality comparator for specific types
 */
type TypeEqualityComparator<Type, Meta> = (
  a: Type,
  b: Type,
  isEqual: InternalEqualityComparator<Meta>,
  meta: Meta
) => boolean;
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/fast-equals@4.0.x
Publish Source
CLI
Badge
tessl/npm-fast-equals badge