Check objects deep equality in TypeScript

When we use the equality operators to compare objects, we are only comparing them by reference, so it returns true only when they are the same instance of the object, for example:

type Person = {
  name: string;
};

const person1: Person = {
  name: 'John Doe',
};

const person2: Person = {
  name: 'John Doe',
};

person1 === person2; // <-- This is false

As you can see in the code snippet, person1 and person2 have the same values, but when comparing them using the equality operator, it returns false (Which means that they are different), that’s because the equality operator is comparing them by reference.

This behavior can be useful in some scenarios, but if we need to compare two objects by their values, we need to compare them using deep equality:

function deepEqual<T>(object1: T, object2: T): boolean {
  // Get the objects keys
  const keys1 = Object.keys(object1);
  const keys2 = Object.keys(object2);

  // Compares if the number of keys of the objects is different
  if (keys1.length !== keys2.length) {
    return false;
  }

  // loop for-of: To loop through the values of an iterable object
  for (const key of keys1) {
    const value1 = object1[key];
    const value2 = object2[key];

    if (isObject(value1) && isObject(value2)) {
      // Both are objects, so compare them using deepEqual
      if (!deepEqual(value1, value2)) return false;
    } else {
      // Both aren't objects, so compare them using equality operator
      if (value1 !== value2) return false;
    }
  }

  return true;
}

// Helper function to check if the parameter is an object
function isObject(object): boolean {
  return object != null && typeof object === 'object';
}

This function loops through each value of the object and uses recursion if it finds any nested objects.

Now let’s see deep equality in action:

type Person = {
  name: string;
  values: number[];
};

const person1: Person = {
  name: 'John Doe',
  values: [1, 3, 5],
};

const person2: Person = {
  name: 'John Doe',
  values: [1, 3, 5],
};

deepEqual(person1, person2); // <---- This is true

As you can see in the code snippet, person1 and person2 have the same values, and comparing them using the deepEqual function, it return true (Which means that they are equals).