type PlainObject = Record export function deepMerge(baseValue: T, overrideValue: PlainObject): T { if (!isPlainObject(baseValue)) { return cloneValue(overrideValue) as T } const result = cloneValue(baseValue) as PlainObject if (!isPlainObject(overrideValue)) { return result as T } for (const [key, value] of Object.entries(overrideValue)) { if (isPlainObject(value) && isPlainObject(result[key])) { result[key] = deepMerge(result[key] as PlainObject, value) continue } result[key] = cloneValue(value) } return result as T } function cloneValue(value: T): T { if (Array.isArray(value)) { return value.map((item) => cloneValue(item)) as T } if (isPlainObject(value)) { const output: PlainObject = {} for (const [key, item] of Object.entries(value)) { output[key] = cloneValue(item) } return output as T } return value } export function isPlainObject(value: unknown): value is PlainObject { return Object.prototype.toString.call(value) === '[object Object]' }