Well, @Bergi's comment is right of course, I should provide my attempt at a solution.
So far my best version is the following. I'll update when I find something nicer. (EDIT: updated, now with overloads and typing):
function merge<K>(a:K, b:K):K;
function merge<T, K>(a: Map<T, K>, b: Map<T, K>): Map<T, K>;
function merge<T, K>(a: Map<T, K>, b: Map<T, K>):any{
// overload 1
if (!(typeof (a) == "object")) {
return b;
}
if (!(typeof (b) == "object")) {
return a;
}
// overload 2
let merged = new Map();
a.forEach((a_value, key)=>{
const b_value = b.get(key);
if(b_value){
merged.set(key, merge(a_value, b_value));
}
else{
merged.set(key, a_value);
}
})
b.forEach((b_value, key)=>{
const a_value = a.get(key);
if(!a_value){
merged.set(key, b_value);
}
})
return merged;
}
let a = new Map<string, Map<string, number>>();
a.set('a', new Map(Object.entries({ 'c': 1 })));
a.set('b', new Map(Object.entries({ 'c': 1 })));
let b = new Map<string, Map<string, number>>();
b.set('b', new Map(Object.entries({ 'd': 2 })));
let merged = merge(a,b);
console.log(merged)