Skip to content

Instantly share code, notes, and snippets.

@wilsoncook
Last active July 16, 2020 13:33
Show Gist options
  • Save wilsoncook/fcc830e5fa87afbf876696bf7a7f6bb1 to your computer and use it in GitHub Desktop.
Save wilsoncook/fcc830e5fa87afbf876696bf7a7f6bb1 to your computer and use it in GitHub Desktop.
Fill target with default values by source via immutable, better than fp.defaultsDeep()
/**
* Fill target with default values by source via immutable
* Benefits: unlike fp.defaultsDeep(), we don't deep clone target to get the real immutable.
* @param target target
* @param source source
* @param options.ignoreArray whether append elements to array
*/
export function immutableDefaultsDeep(target: any, source: any, options?: { ignoreArray?: boolean }): any {
const targetType = typeof target;
const sourceType = typeof source;
// non-empty object or array, append value recursively
if (targetType === 'object' && targetType === sourceType && target !== null && source !== null) {
// don't append elements to array
if (options?.ignoreArray && Array.isArray(target)) {
return target;
}
let newTarget = target;
Object.keys(source).forEach(key => {
const subTarget = immutableDefaultsDeep(newTarget[key], source[key], options);
if (subTarget !== newTarget[key]) {
if (Array.isArray(newTarget)) {
newTarget = [...newTarget];
newTarget[key] = subTarget;
} else {
newTarget = { ...newTarget, [key]: subTarget };
}
}
});
return newTarget;
}
// target is undefined, return source
if (targetType === 'undefined') {
return source;
}
// others: return target
// 1.target is object && typeof target !== typeof source
// 2.target is null
// 3.target is number
// 4.target is string
// 5.target is symbol
// 6.target is function
// 7.target is boolean
// 8.target is bigint
return target;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment