feat(projects): theme init supports initialization based on initial values.

This commit is contained in:
Azir
2024-12-03 16:34:54 +08:00
parent 38962bf00d
commit 823908afca
4 changed files with 81 additions and 8 deletions

View File

@@ -1,3 +1,4 @@
import { isObject } from 'lodash-es';
import { $t } from '@/locales';
/**
@@ -56,3 +57,71 @@ export function toggleHtmlClass(className: string) {
remove
};
}
type AnyObject = { [key: string]: any };
/** Auxiliary type: recursively make all attributes optional */
type PartialDeep<T> = {
[P in keyof T]?: T[P] extends AnyObject ? PartialDeep<T[P]> : T[P];
};
/**
* Deeply update base objects without adding keys that do not exist in the base.
*
* @example
* const base = {
* a: 1,
* b: {
* c: 2,
* d: 3,
* },
* e: [1, 2, 3],
* };
*
* const updates = {
* a: 10,
* b: {
* c: 20,
* e: 30, // Does not exist in base. b, will be ignored
* },
* f: 40, // Does not exist in base. b, will be ignored
* e: [4, 5], // Array will be replaced
* };
*
* const updatedBase = updateBase(base, updates);
*
* console.log(updatedBase);
* output:
* {
* a: 10,
* b: {
* c: 20,
* d: 3
* },
* e: [4, 5]
* }
*
* @param base - Base object
* @param updates - Update object
* @returns New object, a deep copy of the base object with updates applied
*/
export function updateBase<T extends AnyObject>(base: T, updates: PartialDeep<T>): T {
// Deep copy the base object to avoid modifying the original object
const result: AnyObject = Array.isArray(base) ? [...base] : { ...base };
for (const key in updates) {
if (Object.hasOwn(base, key)) {
const baseValue = base[key];
const updateValue = updates[key];
if (isObject(baseValue) && isObject(updateValue)) {
// Recursively update nested objects
result[key] = updateBase(baseValue, updateValue);
} else {
// Directly assign updates
result[key] = updateValue;
}
}
// If the key in updates does not exist in base, ignore it
}
return result as T;
}