diff --git a/dist/types/typeUtils/MergeDeep.d.ts b/dist/types/typeUtils/MergeDeep.d.ts index 10e0f0e..3e679ff 100644 --- a/dist/types/typeUtils/MergeDeep.d.ts +++ b/dist/types/typeUtils/MergeDeep.d.ts @@ -21,9 +21,9 @@ declare type RequiredKeys = O extends unknown ? { [K in keyof O]-?: {} extends Pick ? never : K; }[keyof O] : never; declare type MergeObjectDeeply, O1 extends Record> = { - [K in keyof (O & O1)]: K extends RequiredKeys ? O1[K] : K extends OptionalKeys ? K extends OptionalKeys ? MergeObjectOrReturnUnion, Exclude> : K extends RequiredKeys ? Exclude extends O[K] ? O[K] : MergeObjectOrReturnUnion> : O1[K] : O[K]; + [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]; }; -declare type MergeObjectOrReturnUnion = Val0 extends Record ? Val1 extends Record ? MergeObjectDeeply : Val0 | Val1 : Val0 | Val1; +declare 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]] @@ -35,31 +35,22 @@ declare type MergeObjectOrReturnUnion = Val0 extends Record - * // { - * // name?: string; - * // age: number; - * // zip: number | undefined; - * // pay: { - * // cvv: number; - * // ccn?: string; - * // }; - * // city: string; - * // } + * 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 declare type MergeDeep, O1 extends Record> = O extends unknown ? (O1 extends unknown ? MergeObjectDeeply : never) : never; diff --git a/src/typeUtils/MergeDeep.ts b/src/typeUtils/MergeDeep.ts index a04fdf6..cb4f472 100644 --- a/src/typeUtils/MergeDeep.ts +++ b/src/typeUtils/MergeDeep.ts @@ -1,5 +1,3 @@ -import { PrettyPrint } from './PrettyPrint' - /** * Get the keys of `O` that are optional * @param O @@ -35,23 +33,34 @@ type MergeObjectDeeply< O1 extends Record > = { [K in keyof (O & O1)]: K extends RequiredKeys // second prop is non-optional - ? O1[K] // return second prop + ? MergeObjectsOrReturnFallback // return second prop : K extends OptionalKeys // second prop is optional ? K extends OptionalKeys // first prop is optional (second prop also) - ? MergeObjectOrReturnUnion, Exclude> // return union + ? MergeObjectsOrReturnFallback< + Exclude, + Exclude, + Exclude | Exclude + > // return union : K extends RequiredKeys // first prop required (second prop optional) ? Exclude extends O[K] // (optional) second prop has the same type as the (required) first prop ? O[K] // return only the first one - : MergeObjectOrReturnUnion> // (optional) second prop has a different type as the (required) first prop, so return union without `undefined` in the second + : MergeObjectsOrReturnFallback< + O[K], + Exclude, + O[K] | Exclude + > // (optional) second prop has a different type as the (required) first prop, so return union without `undefined` in the second : O1[K] // first prop inexistent, so return second prop : O[K] // second prop inexistent, so return first prop } -type MergeObjectOrReturnUnion = Val0 extends Record - ? Val1 extends Record - ? MergeObjectDeeply - : Val0 | Val1 - : Val0 | Val1 +type MergeObjectsOrReturnFallback = O extends Record< + string | number | symbol, + unknown +> + ? O1 extends Record + ? MergeObjectDeeply + : Fallback + : Fallback /** * Accurately merge the fields of `O` with the ones of `O1`. It is @@ -64,31 +73,22 @@ type MergeObjectOrReturnUnion = Val0 extends Record - * // { - * // name?: string; - * // age: number; - * // zip: number | undefined; - * // pay: { - * // cvv: number; - * // ccn?: string; - * // }; - * // city: string; - * // } + * 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< @@ -96,32 +96,7 @@ export type MergeDeep< O1 extends Record > = O extends unknown ? (O1 extends unknown ? MergeObjectDeeply : never) : never -// type O = { -// name?: string -// age?: number -// zip?: string -// pay: { cvv?: number; xyz: RegExp } -// } - -// type O1 = { -// age: number -// zip?: number -// pay: { cvv: number; ccn?: string } -// city: string -// } - -// type test = MergeDeep -// { -// name?: string; -// age: number; -// zip: number | undefined; -// pay: { -// cvv: number; -// ccn?: string; -// }; -// city: string; -// } - +// import { PrettyPrint } from './PrettyPrint' // type A1 = { arr: string[]; barr?: { b: number } } // type A2 = { arr?: number[]; barr?: { b: number } } // type TestA = PrettyPrint> @@ -130,6 +105,10 @@ export type MergeDeep< // type B2 = { a?: number; c?: number; d?: number; e: number; x: number | undefined; y?: string; z?: number; } // prettier-ignore // type TestB = PrettyPrint> +// type C1 = { info: { time: string; newDate: Date; very: { deep: { prop: boolean } } } } +// type C2 = { info: { date: string; very: { deep: { prop: boolean } } } } +// type TestC = PrettyPrint> + // import { Timestamp } from 'firebase/firestore' // type T1 = { date: Timestamp } // type T2 = { date: Timestamp }