Skip to content

Commit

Permalink
fix(theme): merge optional params (#256)
Browse files Browse the repository at this point in the history
Allow the option to merge optional partial params on a partial `Theme`.

fix #253
  • Loading branch information
nickofthyme authored Jul 2, 2019
1 parent fc6640d commit 9cd660c
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/lib/themes/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,5 +224,5 @@ export function mergeWithDefaultAnnotationRect(config?: Partial<RectAnnotationSt
}

export function mergeWithDefaultTheme(theme: PartialTheme, defaultTheme: Theme = LIGHT_THEME): Theme {
return mergePartial(defaultTheme, theme);
return mergePartial(defaultTheme, theme, { mergeOptionalPartialValues: true });
}
75 changes: 75 additions & 0 deletions src/lib/utils/commons.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,80 @@ describe('commons utilities', () => {
mergePartial(base, partial);
expect(base).toEqual(baseClone);
});

describe('MergeOptions', () => {
describe('mergeOptionalPartialValues', () => {
interface OptionalTestType {
value1: string;
value2?: number;
value3: string;
value4?: OptionalTestType;
}
const defaultBase: OptionalTestType = {
value1: 'foo',
value3: 'bar',
value4: {
value1: 'foo',
value3: 'bar',
},
};
const partial1: RecursivePartial<OptionalTestType> = { value1: 'baz', value2: 10 };
const partial2: RecursivePartial<OptionalTestType> = { value1: 'baz', value4: { value2: 10 } };

describe('mergeOptionalPartialValues is true', () => {
test('should merge optional parameters', () => {
const merged = mergePartial(defaultBase, partial1, { mergeOptionalPartialValues: true });
expect(merged).toEqual({
value1: 'baz',
value2: 10,
value3: 'bar',
value4: {
value1: 'foo',
value3: 'bar',
},
});
});

test('should merge nested optional parameters', () => {
const merged = mergePartial(defaultBase, partial2, { mergeOptionalPartialValues: true });
expect(merged).toEqual({
value1: 'baz',
value3: 'bar',
value4: {
value1: 'foo',
value2: 10,
value3: 'bar',
},
});
});
});

describe('mergeOptionalPartialValues is false', () => {
test('should NOT merge optional parameters', () => {
const merged = mergePartial(defaultBase, partial1, { mergeOptionalPartialValues: false });
expect(merged).toEqual({
value1: 'baz',
value3: 'bar',
value4: {
value1: 'foo',
value3: 'bar',
},
});
});

test('should NOT merge nested optional parameters', () => {
const merged = mergePartial(defaultBase, partial2, { mergeOptionalPartialValues: false });
expect(merged).toEqual({
value1: 'baz',
value3: 'bar',
value4: {
value1: 'foo',
value3: 'bar',
},
});
});
});
});
});
});
});
30 changes: 21 additions & 9 deletions src/lib/utils/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export type RecursivePartial<T> = {
: RecursivePartial<T[P]>
};

export interface MergeOptions {
mergeOptionalPartialValues?: boolean;
}

/**
* Merges values of a partial structure with a base structure.
*
Expand All @@ -50,18 +54,26 @@ export type RecursivePartial<T> = {
*
* @returns new base structure with updated partial values
*/
export function mergePartial<T>(base: T, partial?: RecursivePartial<T>): T {
export function mergePartial<T>(base: T, partial?: RecursivePartial<T>, options: MergeOptions = {}): T {
if (Array.isArray(base)) {
return partial ? (partial as T) : base; // No nested array merging
} else if (typeof base === 'object') {
return Object.keys(base).reduce(
(newBase, key) => {
// @ts-ignore
newBase[key] = mergePartial(base[key], partial && partial[key]);
return newBase;
},
{ ...base },
);
const baseClone = { ...base };

if (partial && options.mergeOptionalPartialValues) {
Object.keys(partial).forEach((key) => {
if (!(key in baseClone)) {
// @ts-ignore
baseClone[key] = partial[key];
}
});
}

return Object.keys(base).reduce((newBase, key) => {
// @ts-ignore
newBase[key] = mergePartial(base[key], partial && partial[key], options);
return newBase;
}, baseClone);
}

return partial !== undefined ? (partial as T) : base;
Expand Down

0 comments on commit 9cd660c

Please sign in to comment.