Skip to content

isShallowEqual function ​

Checks whether two values are equal at the first level, with Object.is: skips an update when a new object carries the same values as the previous one.

ts
import { isShallowEqual } from 'utils';

Signature ​

ts
export function isShallowEqual(a: unknown, b: unknown): boolean

Parameters ​

NameDescription
aThe first value.
bThe second value.

Returns ​

true when both values are shallowly equal; nested objects are compared by reference.

Example ​

ts
isShallowEqual({ x: 1, y: 2 }, { y: 2, x: 1 }); // true
isShallowEqual({ p: { x: 1 } }, { p: { x: 1 } }); // false

Tests ​

Line coverage: 100 %.

  • ✅ compares 1 and 1 as true
  • ✅ compares null and null as true
  • ✅ compares 0 and 0 as false
  • ✅ compares "a" and "b" as false
  • ✅ compares null and null as true
  • ✅ compares null and {} as false
  • ✅ compares {"x":1,"y":2} and {"y":2,"x":1} as true
  • ✅ compares {"x":1} and {"x":1,"y":2} as false
  • ✅ compares {"x":1} and {"x":1} as false
  • ✅ compares {"x":1} and {"x":2} as false
  • ✅ compares [1,2] and [1,2] as true
  • ✅ compares [1,2] and {"0":1,"1":2} as false
  • ✅ compares {"p":{"x":1}} and {"p":{"x":1}} as false
  • ✅ accepts shared nested references

Source ​

src/object/is-shallow-equal.ts (on GitHub)

Uses ​

  • isObject: Checks whether a value is a non-null object: plain object, array, class instance, date… isRecord accepts plain objects only.

Files it needs ​

src/object/is-shallow-equal.ts imports, directly or not:

Source code
ts
import { isObject } from '../guard';

/**
 * Checks whether two values are equal at the first level, with `Object.is`: skips an update when a new object carries the
 * same values as the previous one.
 *
 * @param a - The first value.
 * @param b - The second value.
 * @returns `true` when both values are shallowly equal; nested objects are compared by reference.
 * @example
 * isShallowEqual({ x: 1, y: 2 }, { y: 2, x: 1 }); // true
 * isShallowEqual({ p: { x: 1 } }, { p: { x: 1 } }); // false
 */
export function isShallowEqual(a: unknown, b: unknown): boolean {
  if (Object.is(a, b)) {
    return true;
  }
  if (!isObject(a) || !isObject(b) || Array.isArray(a) !== Array.isArray(b)) {
    return false;
  }
  const keys = Object.keys(a);
  return (
    keys.length === Object.keys(b).length &&
    keys.every((key) => Object.hasOwn(b, key) && Object.is(Reflect.get(a, key), Reflect.get(b, key)))
  );
}
Test file
ts
import { isShallowEqual } from './is-shallow-equal';

describe(isShallowEqual, () => {
  it.for([
    [1, 1, true],
    [NaN, NaN, true],
    [0, -0, false],
    ['a', 'b', false],
    [null, null, true],
    [null, {}, false],
    [{ x: 1, y: 2 }, { y: 2, x: 1 }, true],
    [{ x: 1 }, { x: 1, y: 2 }, false],
    [{ x: 1, y: undefined }, { x: 1, z: undefined }, false],
    [{ x: 1 }, { x: 2 }, false],
    [[1, 2], [1, 2], true],
    [[1, 2], { 0: 1, 1: 2 }, false],
    [{ p: { x: 1 } }, { p: { x: 1 } }, false],
  ] as const)('compares %j and %j as %s', ([a, b, expected]) => {
    expect(isShallowEqual(a, b)).toBe(expected);
  });

  it('accepts shared nested references', () => {
    const point = { x: 1 };
    expect(isShallowEqual({ point }, { point })).toBe(true);
  });
});

Keywords: is, shallow, equal, objects, function

Generated from the JSDoc of the sources.