Avoid the object/array check and treat the return value the same way with JavaScript spread operator?

I’m trying to implement a function (a template-helper function) which provides a simple merge-like functionality for both arrays and objects. The two functions are basically looks identical:

const mergeArrays = (first, ...rest) =>
  rest.reduce((acc, curr) => (( ...acc, ...curr)), first);

const mergeObjects = (first, ...rest) =>
  rest.reduce((acc, curr) => ({ ...acc, ...curr }), first);

One could do a type check and a local variable to write a single function like this:

const mergeArraysOrObjects1 = (first, ...rest) => {
  let reducer = null;
  if ('object' === typeof first && null !== first) {
    reducer = (acc, curr) => ({ ...acc, ...curr });
  }
  if (Array.isArray(first)) {
    reducer = (acc, curr) => (...acc, ...curr);
  }

  if (!reducer) {
    throw new Error('The "merge" filter only works with arrays and hashes.');
  }

  return rest.reduce(reducer, first);
}

… but it seems so ugly to me. Another possibility is a type check and inline conditional:

const mergeArraysOrObjects2 = (first, ...rest) => {
  if ('object' !== typeof first || null === first) {
    throw new Error('The "merge" filter only works with arrays and hashes.');
  }

  return rest.reduce(
    (acc, curr) => Array.isArray(acc) ? (...acc, ...curr) : {...acc, ...curr},
    first
  );
}

I’m still learning JavaScript so I’m guessing if there is a more elegant and concise way to treat the return value the same way.