import { assert } from "tsafe/assert"; import { is } from "tsafe/is"; import { structuredCloneButFunctions } from "./structuredCloneButFunctions"; //Warning: Be mindful that because of array this is not idempotent. export function deepAssign(params: { target: Record; source: Record; }) { const { target } = params; const source = structuredCloneButFunctions(params.source); Object.keys(source).forEach(key => { var dereferencedSource = source[key]; if ( target[key] === undefined || dereferencedSource instanceof Function || !(dereferencedSource instanceof Object) ) { Object.defineProperty(target, key, { enumerable: true, writable: true, configurable: true, value: dereferencedSource }); return; } const dereferencedTarget = target[key]; if (dereferencedSource instanceof Array) { assert(is(dereferencedTarget)); assert(is(dereferencedSource)); dereferencedSource.forEach(entry => dereferencedTarget.push(entry)); return; } assert(is>(dereferencedTarget)); assert(is>(dereferencedSource)); deepAssign({ target: dereferencedTarget, source: dereferencedSource }); }); }