merge.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { Cast, Head, Push, Resolve, Shift } from '../../../types';
  2. import { slice } from '../../arrayLike';
  3. import { isArray, isObject } from '../../type/type';
  4. import { forOwn } from '../forOwn/forOwn';
  5. /**
  6. * Merges U to T.
  7. *
  8. * @typeParam T - An object to merge U into.
  9. * @typeParam U - An object to merge properties from.
  10. *
  11. * @return A merged object type.
  12. */
  13. export type Merge<T extends object, U extends object> = Omit<T, keyof U> & {
  14. [ K in ( keyof T & keyof U ) ]: U[ K ] extends object
  15. ? U[ K ] extends any[]
  16. ? T[ K ] extends any[]
  17. ? Array<T[ K ][ number ] | U[ K ][ number ]>
  18. : U[ K ]
  19. : T[ K ] extends object
  20. ? Merge<T[ K ], U[ K ]> extends infer A ? Resolve<Cast<A, object>> : never
  21. : U[ K ]
  22. : U[ K ];
  23. } & Omit<U, keyof T>;
  24. /**
  25. * Recursively merges U[] to T.
  26. *
  27. * @typeParam T - An object to assign to.
  28. * @typeParam U - A tuple contains objects.
  29. *
  30. * @return An assigned object type.
  31. */
  32. export type Merged<T extends object, U extends object[], N extends number, C extends any[] = []> = {
  33. 0: T,
  34. 1: Merged<Merge<T, Head<U>>, Shift<U>, N, Push<C>>,
  35. }[ C['length'] extends N ? 0 : 1 ] extends infer A ? Cast<A, any> : never;
  36. export function merge<T extends object>( object: T ): T;
  37. export function merge<T extends object, U extends object[]>(
  38. object: T,
  39. ...sources: U
  40. ): Resolve<Merged<T, U, U['length']>>
  41. /**
  42. * Recursively merges source properties to the object.
  43. * Be aware that this method does not merge arrays. They are just duplicated by `slice()`.
  44. *
  45. * @param object - An object to merge properties to.
  46. *
  47. * @return A new object with merged properties.
  48. */
  49. export function merge<T extends object>( object: T ): any {
  50. slice( arguments ).forEach( source => {
  51. forOwn( source, ( value, key ) => {
  52. if ( isArray( value ) ) {
  53. object[ key ] = value.slice();
  54. } else if ( isObject( value ) ) {
  55. object[ key ] = merge( isObject( object[ key ] ) ? object[ key ] : {}, value );
  56. } else {
  57. object[ key ] = value;
  58. }
  59. } );
  60. } );
  61. return object;
  62. }