File size: 1,048 Bytes
96dd062
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
type Mergeable =
	| Record<string, unknown>
	| unknown[]
	| string
	| number
	| boolean
	| null
	| undefined;

function isPlainObject(value: unknown): value is Record<string, unknown> {
	return typeof value === "object" && value !== null && !Array.isArray(value);
}

export function mergeConfig<T extends Mergeable>(base: T, override: unknown): T {
	if (override === undefined || override === null) {
		return base;
	}

	if (Array.isArray(base)) {
		return (Array.isArray(override) ? [...override] : [...base]) as T;
	}

	if (isPlainObject(base)) {
		if (!isPlainObject(override)) {
			return { ...base } as T;
		}

		const result: Record<string, unknown> = { ...base };
		for (const [key, value] of Object.entries(override)) {
			const baseValue = result[key];
			if (Array.isArray(value)) {
				result[key] = [...value];
				continue;
			}
			if (isPlainObject(baseValue) && isPlainObject(value)) {
				result[key] = mergeConfig(baseValue, value);
				continue;
			}
			result[key] = value;
		}
		return result as T;
	}

	return override as T;
}