I am using lodash merge to merge two objects. The types for lodash (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/bab9c9aef2477d222f014a25ce86585af76c3a5c/types/lodash/common/object.d.ts#L1718) simply rely on intersection types which have some shortcomings when it comes to arrays.
Say I want to merge objects with these types
interface One {
str: string;
arr: Array<{ foo: string }>;
}
interface Two {
num: number;
arr: Array<{ bar: string }>;
}
When these objects are merged with lodash merge the resulting shape is
interface Merged {
str: string;
num: number;
arr: Array<{ foo: string; bar: string }>;
}
But this is not how intersection types work (rationale here). What you end up with for the type of arr is Array<{ foo: string; }> & Array<{ bar: string }> which has this problem:
declare const test: Array<{ foo: string }> & Array<{ bar: string }>;
test.forEach((item) => item.bar); // Property 'bar' does not exist on type '{ foo: string; }'.(2339)
Can a better type for merge be defined such that for arrays Array<A> and Array<B> you get Array<A & B> instead of Array<A> & Array<B>? It would have to be some kind of recursive mapped type, but I didn't have any luck writing one.