Hone logo
Hone
Problems

Vue Patch Object Implementation

Vue.js provides a powerful mechanism for managing and updating component data reactively. A common pattern is to update a complex object by providing a "patch" object, which specifies only the parts of the original object that need to be changed. This challenge asks you to implement a function that simulates this Vue.js patching behavior in TypeScript.

Problem Description

Your task is to create a TypeScript function named patchObject that takes two arguments:

  1. target: The original object to be patched.
  2. patch: An object containing the properties and their new values that should be applied to the target object.

The function should return a new object that represents the patched version of the target object. This means:

  • Properties present in patch should overwrite their corresponding properties in target.
  • Properties not present in patch should retain their original values from target.
  • If a property in patch is undefined, it should be treated as a valid value and overwrite the corresponding property in target (similar to how Object.assign behaves).
  • The function should handle nested objects. If a property in patch is an object and its corresponding property in target is also an object, the function should recursively patch the nested object.
  • The original target object must not be mutated. The function should return a completely new object.

Examples

Example 1:

Input:
target = {
  name: "Alice",
  age: 30,
  address: {
    street: "123 Main St",
    city: "Anytown"
  }
}
patch = {
  age: 31,
  address: {
    city: "Otherville"
  }
}

Output:
{
  name: "Alice",
  age: 31,
  address: {
    street: "123 Main St",
    city: "Otherville"
  }
}
Explanation:
The 'age' property is updated to 31.
The 'address' object is patched: 'city' is updated to "Otherville", while 'street' remains unchanged.
The 'name' property is not in the patch and remains "Alice".

Example 2:

Input:
target = {
  id: 1,
  settings: {
    theme: "dark",
    notifications: true
  }
}
patch = {
  settings: {
    notifications: false,
    language: "en"
  },
  isActive: true
}

Output:
{
  id: 1,
  settings: {
    theme: "dark",
    notifications: false,
    language: "en"
  },
  isActive: true
}
Explanation:
The 'settings' object is patched: 'notifications' is updated, and 'language' is added. 'theme' is retained.
The 'isActive' property is new and added to the root object.
The 'id' property is retained.

Example 3: Handling undefined and non-object types

Input:
target = {
  value: 10,
  config: {
    enabled: true,
    threshold: 5
  },
  optional: "present"
}
patch = {
  value: undefined,
  config: {
    enabled: false,
    threshold: null // null is a valid value
  },
  optional: undefined, // undefined should overwrite
  newField: "added"
}

Output:
{
  value: undefined,
  config: {
    enabled: false,
    threshold: null
  },
  optional: undefined,
  newField: "added"
}
Explanation:
'value' is set to undefined.
'config' is patched: 'enabled' becomes false, 'threshold' becomes null.
'optional' is set to undefined, overwriting its previous value.
'newField' is added.

Constraints

  • The target and patch objects can have arbitrary levels of nesting.
  • The function should be efficient, ideally performing a shallow copy for non-nested properties and a deep copy only where necessary.
  • Input types for target and patch will always be Record<string, any> or a subtype thereof.
  • The function should return Record<string, any> or a subtype thereof.

Notes

  • Consider how to differentiate between an object that needs to be deeply patched and other object types (like Dates, Arrays, etc.). For this challenge, assume that only plain JavaScript objects (typeof value === 'object' && value !== null && !Array.isArray(value)) should be recursively patched. Other object types should be treated as primitive values and overwritten directly.
  • Think about how to iterate through the properties of both the target and patch objects.
  • The core of the challenge lies in correctly handling the recursive patching of nested objects while ensuring immutability.
Loading editor...
typescript