deep-merge-arrays.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /**
  2. * @fileoverview Applies default rule options
  3. * @author JoshuaKGoldberg
  4. */
  5. /**
  6. * Check if the variable contains an object strictly rejecting arrays
  7. * @param {unknown} value an object
  8. * @returns {boolean} Whether value is an object
  9. */
  10. function isObjectNotArray(value) {
  11. return typeof value === "object" && value !== null && !Array.isArray(value);
  12. }
  13. /**
  14. * Deeply merges second on top of first, creating a new {} object if needed.
  15. * @param {T} first Base, default value.
  16. * @param {U} second User-specified value.
  17. * @returns {T | U | (T & U)} Merged equivalent of second on top of first.
  18. */
  19. function deepMergeObjects(first, second) {
  20. if (second === void 0) {
  21. return first;
  22. }
  23. if (!isObjectNotArray(first) || !isObjectNotArray(second)) {
  24. return second;
  25. }
  26. const result = { ...first, ...second };
  27. for (const key of Object.keys(second)) {
  28. if (Object.prototype.propertyIsEnumerable.call(first, key)) {
  29. result[key] = deepMergeObjects(first[key], second[key]);
  30. }
  31. }
  32. return result;
  33. }
  34. /**
  35. * Deeply merges second on top of first, creating a new [] array if needed.
  36. * @param {T[] | undefined} first Base, default values.
  37. * @param {U[] | undefined} second User-specified values.
  38. * @returns {(T | U | (T & U))[]} Merged equivalent of second on top of first.
  39. */
  40. function deepMergeArrays(first, second) {
  41. if (!first || !second) {
  42. return second || first || [];
  43. }
  44. return [
  45. ...first.map((value, i) => deepMergeObjects(value, second[i])),
  46. ...second.slice(first.length)
  47. ];
  48. }
  49. export { deepMergeArrays };