how to merge two nested objects with one taking precedence in typescript

You can create a function that receives two objects with optional nested properties as argument and merge them recursively, giving precedence to the properties of the first object.

Here is an example implementation:

index.ts
type NestedObject = { [key: string]: any } | NestedObject[];

function mergeNestedObjects(obj1: NestedObject, obj2: NestedObject): NestedObject {
  if (Array.isArray(obj1) || Array.isArray(obj2)) {
    // if one of the arguments is an array, concatenate them
    return [...(obj1 as any[]), ...(obj2 as any[])];
  } else {
    // otherwise, merge the objects recursively
    const mergedObject: NestedObject = { ...(obj2 as object) };
    for (const key in obj1) {
      if (obj1.hasOwnProperty(key)) {
        const value1 = obj1[key];
        const value2 = obj2[key];
        if (value2 && typeof value1 === "object" && typeof value2 === "object") {
          mergedObject[key] = mergeNestedObjects(value1, value2);
        } else {
          mergedObject[key] = value1;
        }
      }
    }
    return mergedObject;
  }
}
829 chars
24 lines

You can then use this function like this:

index.ts
const obj1 = {
  foo: "bar",
  nested: {
    a: true,
    b: 123,
    c: {
      d: "hello",
      e: {
        f: ["world"],
      },
    },
  },
};

const obj2 = {
  nested: {
    a: false,
    c: {
      d: "world",
      e: {
        f: ["hello"],
        g: 456,
      },
    },
  },
  extra: "property",
};

const mergedObj = mergeNestedObjects(obj1, obj2);
console.log(mergedObj);
388 chars
31 lines

This will output:

index.ts
{
  "foo": "bar",
  "nested": {
    "a": true,
    "b": 123,
    "c": {
      "d": "hello",
      "e": {
        "f": ["world", "hello"],
        "g": 456
      }
    }
  },
  "extra": "property"
}
198 chars
16 lines

As you can see, the properties of obj1 are kept, except for the ones that are overwritten by obj2. The nested objects are recursively merged, giving precedence to obj1.

related categories

gistlibby LogSnag