-
-
Save barchero/d435ca9aeb809d25f5616c83529ffd76 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Take two objects T and U and create the new one with uniq keys for T a U objectI | |
| * helper generic for `DeepMergeTwoTypes` | |
| */ | |
| type GetObjDifferentKeys<T, U> = Omit<T, keyof U> & Omit<U, keyof T> | |
| /** | |
| * Take two objects T and U and create the new one with the same objects keys | |
| * helper generic for `DeepMergeTwoTypes` | |
| */ | |
| type GetObjSameKeys<T, U> = Omit<T | U, keyof GetObjDifferentKeys<T, U>> | |
| type MergeTwoObjects<T, U> = | |
| // non shared keys are optional | |
| Partial<GetObjDifferentKeys<T, U>> | |
| // shared keys are recursively resolved by `DeepMergeTwoTypes<...>` | |
| & {[K in keyof GetObjSameKeys<T, U>]: DeepMergeTwoTypes<T[K], U[K]>} | |
| // it merge 2 static types and try to avoid of unnecessary options (`'`) | |
| export type DeepMergeTwoTypes<T, U> = | |
| // check if generic types are arrays and unwrap it and do the recursion | |
| [T, U] extends [(infer TItem)[], (infer UItem)[]] | |
| ? DeepMergeTwoTypes<TItem, UItem>[] | |
| // check if generic types are objects | |
| : [T, U] extends [{ [key: string]: unknown}, { [key: string]: unknown } ] | |
| ? MergeTwoObjects<T, U> | |
| : [T, U] extends [{ [key: string]: unknown} | undefined, { [key: string]: unknown } | undefined ] | |
| ? MergeTwoObjects<NonNullable<T>, NonNullable<U>> | undefined | |
| : T | U | |
| // ----------------------------------------- | |
| // make the generic to apply N objects instead of just 2 | |
| type Head<T extends any[]> = | |
| T extends [any, ...any[]] | |
| ? T[0] | |
| : never; | |
| type Length<T extends any[]> = T['length']; | |
| type Tail<T extends any[]> = | |
| T extends [any, ...infer TT] | |
| ? TT | |
| : []; | |
| type DeepMergeResult<CurrResult, Objects extends any[]> = { | |
| 0: CurrResult; | |
| 1: DeepMergeResult<DeepMergeTwoTypes<CurrResult, Head<Objects>>, Tail<Objects>>; | |
| } [ | |
| Length<Objects> extends 0 | |
| ? 0 | |
| : 1 | |
| ]; | |
| type DeepMergeMany<Args extends any[]> = | |
| Args extends [infer Item1, ... infer Rest] | |
| ? DeepMergeResult<Item1, Rest> | |
| : never | |
| // ---------------------------------- | |
| const a = { | |
| onlyField: { | |
| a: { b: 'c' } | |
| }, | |
| arr: [ | |
| [ | |
| { p: 'ahoooj' }, | |
| { | |
| next: 'key' | |
| } | |
| ] | |
| ], | |
| a: { | |
| a: 'a', | |
| b: 'b', | |
| c: { | |
| c: 'c' | |
| }, | |
| q: { | |
| a: { b: { c: 'd' } } | |
| } | |
| }, | |
| kuba: { | |
| a: { | |
| b: 'b' | |
| } | |
| } | |
| }; | |
| const b = { | |
| onlyField: undefined as undefined | null, | |
| arr: [ | |
| [ | |
| { | |
| cau: 'hi' | |
| } | |
| ] | |
| ], | |
| a: { | |
| c: { | |
| qqq: { qq: 'qq' }, | |
| d: 'd' | |
| }, | |
| d: null, | |
| q: { b: { c: 'asdf' } } | |
| }, | |
| samo: { | |
| b: { | |
| a: 'a' | |
| } | |
| } | |
| }; | |
| const c = { | |
| arr: [ | |
| [ | |
| { pozdrav: 'cau' } | |
| ] | |
| ], | |
| a: { | |
| b: undefined | |
| }, | |
| samo: { | |
| a: [ | |
| 1, undefined, null, 43 | |
| ] | |
| }, | |
| kuba: { | |
| a: { | |
| c: 'c' | |
| } | |
| } | |
| }; | |
| const myMerge = <T extends any[]>(...args: T): DeepMergeMany<T> => null as any; | |
| const data = myMerge( | |
| c, | |
| b, | |
| a | |
| ).kuba |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment