rivo
Version:
🤖 The ultimate library you need for composable type-level programming in TypeScript, powered by HKT.
60 lines (54 loc) • 1.89 kB
TypeScript
// @ts-ignore - Only used in doc comments
import type { SimpleMerge } from "./SimpleMerge";
// @ts-ignore - Only used in doc comments
import type SimpleMergeFn from "./SimpleMerge";
import type { Args, Fn } from "../HKT";
import type { AssertObj } from "../helpers";
type _OptionalKeyOf<O> = {
[K in keyof O]-?: NonNullable<unknown> extends { [P in K]: O[K] } ? K : never;
}[keyof O];
type _SpreadProperties<L, R, K extends keyof L & keyof R> = {
[P in K]: L[P] | Exclude<R[P], undefined>;
};
type _Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;
/**
* Merge two objects together. Optional keys are considered.
*
* However, this can cause some performance issues and may break TS in rare cases,
* so it is recommended to use {@link SimpleMerge} when you're sure that
* the two objects have no optional properties.
*
* Sig: `(l: object, r: object) => object`
*
* @example
* ```typescript
* type A = { a: number; b?: string };
* type B = { a: boolean; c: string };
* type R = Merge<A, B>;
* // ^?: { a: boolean; b?: string; c: string }
* ```
*
* @see {@link SimpleMerge}
*/
export type Merge<L extends object, R extends object> = AssertObj<
_Id<
Pick<L, Exclude<keyof L, keyof R>> &
Pick<R, Exclude<keyof R, _OptionalKeyOf<R>>> &
Pick<R, Exclude<_OptionalKeyOf<R>, keyof L>> &
_SpreadProperties<L, R, _OptionalKeyOf<R> & keyof L>
>
>;
/**
* [Fn] Merge two objects together. Optional keys are considered.
*
* However, this can cause some performance issues and may break TS in rare cases,
* so it is recommended to use {@link SimpleMerge} when you're sure that
* the two objects have no optional properties.
*
* Sig: `(l: object, r: object) => object`
*
* @see {@link SimpleMerge}
*/
export default interface MergeFn extends Fn<[object, object], object> {
def: ([l, r]: Args<this>) => Merge<typeof l, typeof r>;
}