Created
December 27, 2024 03:29
-
-
Save teramuza/341ce6f442885ac921d2ca9c4bea1e81 to your computer and use it in GitHub Desktop.
Patching updated data overriding values in `base` with non-empty values from `patch`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Merges two objects (`base` and `patch`) by overriding values in `base` with non-empty values from `patch`. | |
| * | |
| * - If a value in `patch` is `null`, `undefined`, or an empty string (`""`), the corresponding value from `base` is used. | |
| * - For nested objects, the function performs a recursive merge. | |
| * | |
| * This function is useful for scenarios where default values (`base`) need to be preserved unless explicitly replaced | |
| * by valid values from another source (`patch`). | |
| * | |
| * @template T - The type of the objects being merged. Defaults to `object`. | |
| * @param {T} base - The base object containing default values. | |
| * @param {T} patch - The object containing values to override those in `base`. | |
| * @returns {T} - A new object that combines properties from `base` and `patch`. | |
| * | |
| * @example | |
| * // Simple merge | |
| * const base = { name: "John", age: 30 }; | |
| * const patch = { name: "", age: 25 }; | |
| * const result = patchObject(base, patch); | |
| * console.log(result); // { name: "John", age: 25 } | |
| * | |
| * @example | |
| * // Nested merge | |
| * const baseNested = { name: "John", details: { city: "New York", phone: "12345" } }; | |
| * const patchNested = { name: "", details: { city: "Los Angeles" } }; | |
| * const resultNested = patchObject(baseNested, patchNested); | |
| * console.log(resultNested); | |
| * // Output: | |
| * // { name: "John", details: { city: "Los Angeles", phone: "12345" } } | |
| */ | |
| export function patchObject<T extends Record<string, unknown>>( | |
| base: T = {} as T, | |
| patch: T = {} as T, | |
| ): T { | |
| const result = { ...base }; | |
| Object.keys(patch).forEach((key) => { | |
| const patchValue = patch[key as keyof T]; | |
| const baseValue = base[key as keyof T]; | |
| if ( | |
| patchValue === null || | |
| patchValue === '' || | |
| patchValue === undefined | |
| ) { | |
| result[key as keyof T] = baseValue; | |
| } else if ( | |
| typeof patchValue === 'object' && | |
| !Array.isArray(patchValue) | |
| ) { | |
| result[key as keyof T] = patchObject( | |
| (baseValue || {}) as Record<string, unknown>, | |
| patchValue as Record<string, unknown>, | |
| ) as T[keyof T]; | |
| } else { | |
| result[key as keyof T] = patchValue; | |
| } | |
| }); | |
| return result; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment