deepEqual
Performs a deep (structural) equality check between two JavaScript values. It compares arrays, objects, primitives, and nested structures recursively.
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
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.