Created
February 6, 2025 16:52
-
-
Save fmartins-andre/b414b374666e5af1f40366729a7eea68 to your computer and use it in GitHub Desktop.
patchDeep: A function to deeply patch an object
This file contains 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
declare type DeepPartial<T> = { | |
[K in keyof T]?: DeepPartial<T[K]> | undefined | |
} | |
const isObject = (obj: unknown) => obj && typeof obj === 'object' | |
/** | |
* Patch source object with other object. | |
* Only the source object keys are kept! | |
* Patch undefined values are ignored | |
* | |
* @param {TSource} source | |
* @param {TPatch} patch | |
* @return {*} {TSource} | |
*/ | |
export function patchDeep< | |
TSource extends Record<string, unknown>, | |
TPatch extends DeepPartial<TSource>, | |
>(source: TSource, patch: TPatch): TSource { | |
if (!isObject(patch) || !isObject(source)) { | |
return source | |
} | |
const mergedObj = Object.entries(source).reduce( | |
(agg, [sourceKey, sourceValue]): TSource => { | |
const patchValue = patch[sourceKey] | |
if (Array.isArray(sourceValue)) { | |
return { | |
...agg, | |
[sourceKey]: Array.isArray(patchValue) | |
? patchValue.concat(sourceValue) | |
: sourceValue, | |
} | |
} | |
if (isObject(sourceValue)) { | |
return { | |
...agg, | |
[sourceKey]: isObject(patchValue) | |
? patchDeep(sourceValue as TSource, patchValue as TPatch) | |
: sourceValue, | |
} | |
} | |
return { | |
...agg, | |
[sourceKey]: patchValue === undefined ? sourceValue : patchValue, | |
} | |
}, | |
Object.create({}) as TSource | |
) | |
return mergedObj | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment