/** * Get the keys of `O` that are optional * @param O * @returns [[Key]] * @example * ```ts * ``` */ type OptionalKeys = O extends unknown ? { [K in keyof O]-?: {} extends Pick ? K : never; }[keyof O] : never; /** * Get the keys of `O` that are required * @param O * @returns [[Key]] * @example * ```ts * ``` */ type RequiredKeys = O extends unknown ? { [K in keyof O]-?: {} extends Pick ? never : K; }[keyof O] : never; type MergeObjectDeeply, O1 extends Record> = { [K in keyof (O & O1)]: K extends RequiredKeys ? MergeObjectsOrReturnFallback : K extends OptionalKeys ? K extends OptionalKeys ? MergeObjectsOrReturnFallback, Exclude, Exclude | Exclude> : K extends RequiredKeys ? Exclude extends O[K] ? O[K] : MergeObjectsOrReturnFallback, O[K] | Exclude> : O1[K] : O[K]; }; type MergeObjectsOrReturnFallback = O extends Record ? O1 extends Record ? MergeObjectDeeply : Fallback : Fallback; /** * Accurately merge the fields of `O` with the ones of `O1`. It is * equivalent to the spread operator in JavaScript. [[Union]]s and [[Optional]] * fields will be handled gracefully. * * (⚠️ needs `--strictNullChecks` enabled) * @param O to complete * @param O1 to copy from * @returns [[Object]] * @example * ```ts * import { PrettyPrint } from './PrettyPrint' * * type A1 = { a: number; b?: number; d?: number; e?: number; x: string; y?: number; z: string; } // prettier-ignore * type A2 = { a?: number; c?: number; d?: number; e: number; x: number | undefined; y?: string; z?: number; } // prettier-ignore * * type Result = PrettyPrint> * { * a: number; * b?: number | undefined; * c?: number | undefined; * d?: number | undefined; * e: number; * x: number | undefined; * y?: string | number | undefined; * z: string | number; * } * ``` */ export type MergeDeep, O1 extends Record> = O extends unknown ? (O1 extends unknown ? MergeObjectDeeply : never) : never; export {};