Skip to content

Instantly share code, notes, and snippets.

@AyAyEm
Last active October 10, 2022 14:21
Show Gist options
  • Save AyAyEm/53def5b7abfd5cfbfc3674284ec6b26f to your computer and use it in GitHub Desktop.
Save AyAyEm/53def5b7abfd5cfbfc3674284ec6b26f to your computer and use it in GitHub Desktop.
A functional approach to merging objects
export type Obj = Record<string | number | symbol, unknown>;
export function mergeObjects<A extends Obj, B extends Obj>(a: A, b: B): A & B {
if (Array.isArray(a) && Array.isArray(b)) {
return [...a, ...b] as unknown as A & B;
} else if (Array.isArray(b)) {
return b as unknown as A & B;
}
const mappedEntries = [...Object.keys(a), ...Object.keys(b)].map((key) => {
const value = {
a: a[key],
b: b[key],
} as const;
if (!containsKey(key, a)) {
return [key, value.b];
} else if (!containsKey(key, b)) {
return [key, value.a];
}
if (isObject(value.a) && isObject(value.b)) {
return [key, mergeObjects(value.a, value.b)];
}
return [key, value.b];
});
return Object.fromEntries(mappedEntries);
}
function containsKey(
key: string | number | symbol,
obj: { key: unknown }
): true;
// I don't know how to make this typing work as expected
function containsKey<K extends string | number | symbol>(
key: K,
obj: Obj
): obj is { [Key in K]: typeof obj[Key] };
function containsKey(key: string | number | symbol, obj: Obj): boolean {
return !isUndefined(obj[key]);
}
export function isUndefined(value: undefined): true;
export function isUndefined(value: unknown): value is undefined;
export function isUndefined(value: unknown): boolean {
return typeof value === 'undefined';
}
export function isNull(value: null): true;
export function isNull(value: unknown): value is null;
export function isNull(value: unknown): boolean {
return value === null;
}
export function isObject(value: undefined): true;
export function isObject(value: unknown | undefined): value is Obj;
export function isObject(value: unknown): boolean {
return !isUndefined(value) && !isNull(value) && typeof value === 'object';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment