Created
December 10, 2021 00:36
-
-
Save jonfriesen/ae8254bfaa4655d1873580ae1dc1b6ce to your computer and use it in GitHub Desktop.
Opinionated deepmerge
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
/** | |
* deepMerge takes two objects and overwrites the values with | |
* incoming values, if they are empty, undefined, or missing, | |
* the default values will be used. | |
* | |
* In the case of arrays, the first value in the object set | |
* will be used as the template and applied to all values | |
* in the incoming set. | |
*/ | |
function deepMerge(defaultSet, incomingSet) { | |
const isObject = obj => obj && typeof obj === 'object' | |
if (!isObject(defaultSet) || !isObject(incomingSet)) { | |
return incomingSet | |
} | |
let keys = Object.keys(incomingSet) | |
for (let i = 0; i < keys.length; i++) { | |
let key = keys[i] | |
const targetValue = defaultSet[key] | |
const sourceValue = incomingSet[key] | |
if (Array.isArray(targetValue) && sourceValue === undefined || Array.isArray(sourceValue)) { | |
// if the source is not set or empty, use whatever the default is | |
if (sourceValue == undefined || sourceValue.length < 1) { | |
// if sourceValue is empty, use the default array | |
continue; | |
} | |
// we expect the first value in the default object array to be | |
// the template, no other values will be considered. | |
let templatedArrayDefault = targetValue[0] | |
// create a buffer array | |
let filledInArray = [] | |
sourceValue.forEach(v => { | |
// Do a deep clone if possible, so we don't overwrite | |
// any reference type variables. | |
let clonedTemplateValue = templatedArrayDefault | |
if ( | |
templatedArrayDefault instanceof Object && | |
!(templatedArrayDefault instanceof Date) && | |
!(templatedArrayDefault instanceof String) | |
) { | |
clonedTemplateValue = deepClone(templatedArrayDefault) // deepClone(targetValue[0]) | |
} | |
filledInArray.push(deepMerge(clonedTemplateValue, v)) | |
}) | |
defaultSet[key] = filledInArray | |
} else if (isObject(targetValue) && isObject(sourceValue)) { | |
defaultSet[key] = deepMerge(Object.assign({}, targetValue), sourceValue) | |
} else { | |
defaultSet[key] = sourceValue | |
} | |
} | |
return defaultSet | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment