All files / src/support/utils object.ts

100% Statements 26/26
100% Branches 22/22
100% Functions 6/6
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105                14x 540x           1594x                                                                     181x     181x 3x     181x   1086x 598x       598x 1x     597x     597x 123x 123x     123x 30x 93x 76x       123x   474x           181x                 58x 28x      
import { isArray, isFunction, isPlainObject, isNull } from 'support/utils/types';
import { each } from 'support/utils/array';
 
/**
 * Determines whether the passed object has a property with the passed name.
 * @param obj The object.
 * @param prop The name of the property.
 */
export const hasOwnProperty = (obj: any, prop: string | number | symbol): boolean =>
  Object.prototype.hasOwnProperty.call(obj, prop);
 
/**
 * Returns the names of the enumerable string properties and methods of an object.
 * @param obj The object of which the properties shall be returned.
 */
export const keys = (obj: any): Array<string> => (obj ? Object.keys(obj) : []);
 
// https://github.com/jquery/jquery/blob/master/src/core.js#L116
export function assignDeep<T, U>(target: T, object1: U): T & U;
export function assignDeep<T, U, V>(target: T, object1: U, object2: V): T & U & V;
export function assignDeep<T, U, V, W>(
  target: T,
  object1: U,
  object2: V,
  object3: W
): T & U & V & W;
export function assignDeep<T, U, V, W, X>(
  target: T,
  object1: U,
  object2: V,
  object3: W,
  object4: X
): T & U & V & W & X;
export function assignDeep<T, U, V, W, X, Y>(
  target: T,
  object1: U,
  object2: V,
  object3: W,
  object4: X,
  object5: Y
): T & U & V & W & X & Y;
export function assignDeep<T, U, V, W, X, Y, Z>(
  target: T,
  object1?: U,
  object2?: V,
  object3?: W,
  object4?: X,
  object5?: Y,
  object6?: Z
): T & U & V & W & X & Y & Z {
  const sources: Array<any> = [object1, object2, object3, object4, object5, object6];
 
  // Handle case when target is a string or something (possible in deep copy)
  if ((typeof target !== 'object' || isNull(target)) && !isFunction(target)) {
    target = {} as T;
  }
 
  each(sources, (source) => {
    // Extend the base object
    each(keys(source), (key) => {
      const copy: any = source[key];
 
      // Prevent Object.prototype pollution
      // Prevent never-ending loop
      if (target === copy) {
        return true;
      }
 
      const copyIsArray = isArray(copy);
 
      // Recurse if we're merging plain objects or arrays
      if (copy && (isPlainObject(copy) || copyIsArray)) {
        const src = target[key];
        let clone: any = src;
 
        // Ensure proper type for the source value
        if (copyIsArray && !isArray(src)) {
          clone = [];
        } else if (!copyIsArray && !isPlainObject(src)) {
          clone = {};
        }
 
        // Never move original objects, clone them
        target[key] = assignDeep(clone, copy) as any;
      } else {
        target[key] = copy;
      }
    });
  });
 
  // Return the modified object
  return target as any;
}
 
/**
 * Returns true if the given object is empty, false otherwise.
 * @param obj The Object.
 */
export function isEmptyObject(obj: any): boolean {
  /* eslint-disable no-restricted-syntax, guard-for-in */
  for (const name in obj) return false;
  return true;
  /* eslint-enable */
}