Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

deepEqual

Performs a deep (structural) equality check between two JavaScript values. It compares arrays, objects, primitives, and nested structures recursively.

TypeScript
Copied!
1/**
2 * Performs a deep (structural) equality check between two JavaScript values.
3 * It compares arrays, objects, primitives, and nested structures recursively.
4 *
5 * @param a - First value.
6 * @param b - Second value.
7 * @returns True if the values are deeply equal, false otherwise.
8 */
9export function deepEqual(a: any, b: any): boolean {
10  if (a === b) return true;
11  if (typeof a !== typeof b || a === null || b === null) return false;
12
13  if (Array.isArray(a) && Array.isArray(b)) {
14    return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
15  }
16
17  if (typeof a === 'object') {
18    const keysA = Object.keys(a);
19    const keysB = Object.keys(b);
20    if (keysA.length !== keysB.length) return false;
21    return keysA.every(key => deepEqual(a[key], b[key]));
22  }
23
24  return false;
25}
  • Recursive Structure Traversal

    Supports deeply nested objects and arrays, ensuring accurate comparisons beyond shallow equality.

  • Type-Aware Comparison

    Differentiates between primitives, arrays, and objects while ignoring structural mismatches early for performance.

  • Pure & Predictable

    Produces consistent, side-effect-free results without mutating input values.

  • Handles Null and Edge Cases Gracefully

    Explicit checks for null and mismatched types prevent runtime errors and logical misjudgments.

Tests | Examples

TypeScript
Copied!
1test('deepEqual compares primitives', () => {
2  expect(deepEqual(1, 1)).toBe(true);
3  expect(deepEqual('abc', 'abc')).toBe(true);
4  expect(deepEqual(true, false)).toBe(false);
5  expect(deepEqual(null, null)).toBe(true);
6  expect(deepEqual(undefined, undefined)).toBe(true);
7});
8
9test('deepEqual compares arrays', () => {
10  expect(deepEqual([1, 2], [1, 2])).toBe(true);
11  expect(deepEqual([1, [2, 3]], [1, [2, 3]])).toBe(true);
12  expect(deepEqual([1, 2], [2, 1])).toBe(false);
13});
14
15test('deepEqual compares objects', () => {
16  expect(deepEqual({ a: 1, b: 2 }, { b: 2, a: 1 })).toBe(true);
17  expect(deepEqual({ a: { b: [1, 2] } }, { a: { b: [1, 2] } })).toBe(true);
18  expect(deepEqual({ a: 1 }, { a: 1, b: 2 })).toBe(false);
19});
20
21test('deepEqual detects type mismatch', () => {
22  expect(deepEqual({ a: 1 }, [1])).toBe(false);
23  expect(deepEqual([1, 2], { 0: 1, 1: 2 })).toBe(false);
24  expect(deepEqual(null, {})).toBe(false);
25});

Common Use Cases

  • Unit Testing Helpers

    Validate that deeply nested outputs or configurations match expected values in test assertions.

  • React/Redux State Comparison

    Detect structural changes in application state objects to decide when re-renders or updates are necessary.

  • Form Change Detection

    Compare initial form state to current values to determine if the form is dirty.

  • Cache Invalidation or Memoization

    Determine if input parameters have truly changed before triggering expensive recalculations.

Codebase: Utilities -> Validation -> deepEqual | Yevhen Klymentiev