Skip to content

Instantly share code, notes, and snippets.

@akinsho
Created September 1, 2018 10:29
Show Gist options
  • Save akinsho/450e0f262b9ecd7efe405a4918ea21ec to your computer and use it in GitHub Desktop.
Save akinsho/450e0f262b9ecd7efe405a4918ea21ec to your computer and use it in GitHub Desktop.
Deep merge in TS
type Unknown = string | boolean | object | number
function isObject(item: Unknown) {
return item && typeof item === "object" && !Array.isArray(item)
}
const isArray = (elem: Unknown) => Array.isArray(elem)
export default function mergeDeep<T extends object>(target: T, source: T): T {
let output = Object.assign({}, target)
if (isObject(target) && isObject(source)) {
Object.entries(source).forEach(([key, sourceValue]) => {
const targetValue = target[key]
if (isObject(sourceValue)) {
if (!(key in target)) {
Object.assign(output, { [key]: sourceValue })
} else {
output[key] = mergeDeep(targetValue, sourceValue)
}
} else if (isArray(sourceValue) && isArray(targetValue)) {
output[key] = [...sourceValue, ...targetValue]
} else {
Object.assign(output, { [key]: sourceValue })
}
})
}
return output
}
export function mergeAll<T extends object>(...objs: T[]): T {
return objs.reduce((prev, next) => mergeDeep(prev, next), {} as T)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment