Map and Set merging support
RebeccaStevens opened this issue · 1 comments
RebeccaStevens commented
I'm not sure if this is in the scope of this library or not but I think it would be a good to have support for merging Set
s and Map
s out of the box.
I needed support for this functionality for a project I'm working on and so I wrote my own wrapper for this lib to add support. I thought I should drop the code snippet here in case anyone else needed this functionality.
import deepMergeLib from 'deepmerge';
import isPlainObject from 'is-plain-object';
export function mergeMaps<K, V>(
maps: ReadonlyArray<ReadonlyMap<K, V>>,
deep = false
): Map<K, V> {
return maps.reduce<Map<K, V>>((mutableCarry, current) => {
for (const [key, value] of current.entries()) {
const currentValue = mutableCarry.get(key);
mutableCarry.set(
key,
deep && typeof value === 'object' && typeof currentValue === 'object'
? ((deepMerge([
(currentValue as unknown) as object,
(value as unknown) as object,
]) as unknown) as V)
: value
);
}
return mutableCarry;
}, new Map<K, V>());
}
export function mergeSets<V>(sets: ReadonlyArray<ReadonlySet<V>>): Set<V> {
return sets.reduce<Set<V>>((mutableCarry, current) => {
for (const value of current.values()) {
mutableCarry.add(value);
}
return mutableCarry;
}, new Set<V>());
}
export function deepMerge<T extends object>(
values: ReadonlyArray<T>,
options = { mergeMaps: true, mergeSets: true }
): T {
const [mergeAsMaps, mergeAsSets] =
(options.mergeMaps || options.mergeSets) && values.length > 0
? values.reduce(
(carry, value) => [
carry[0] && value instanceof Map,
carry[1] && value instanceof Set,
],
[options.mergeMaps, options.mergeSets]
)
: [false, false];
if (mergeAsSets) {
return mergeSets(values as any) as T;
}
if (mergeAsMaps) {
return mergeMaps(values as any, true) as T;
}
return deepMergeLib.all(values as Array<T>, {
customMerge: () => (a: T, b: T) => deepMerge<T>([a, b], options),
isMergeableObject: (value: object) =>
(options.mergeSets && value instanceof Set) ||
(options.mergeMaps && value instanceof Map) ||
isPlainObject(value),
clone: false,
}) as T;
}
RebeccaStevens commented
I've made my own package now that has builtin support for set and map merging as well as some other benefits. deepmerge-ts