code: function set(base, path, value, { withArrays, sameValue }) {
    if (path.length === 0) {
      return value;
    }
  
    const [key, nextKey] = path;
    const isArrayKeys = Array.isArray(key);
    let currentBase = base;
  
    if (!base || typeof base !== 'object') {
      currentBase = (isArrayKeys && typeof key[0] === 'number') || (withArrays && typeof key === 'number') ? [] : {};
    }
  
    if (isArrayKeys) {
      if (Array.isArray(currentBase)) {
        return reduceWithArray(set)(currentBase, path, key, nextKey, value, { withArrays, sameValue }, [...currentBase]);
      }
  
      return {
        ...currentBase,
        ...reduceWithObject(set)(currentBase, path, key, nextKey, value, { withArrays, sameValue }, {}),
      };
    }
  
    if (Array.isArray(currentBase)) {
      return [
        ...currentBase.slice(0, key),
        set(nextBase(currentBase, key, nextKey, withArrays), path.slice(1), value, { withArrays, sameValue }),
        ...currentBase.slice(key + 1),
      ];
    }
  
    return {
      ...currentBase,
      [key]: set(nextBase(currentBase, key, nextKey, withArrays), path.slice(1), value, { withArrays, sameValue }),
    };
  }
docs: Recursive immutable set
  @param base current base
  @param path current path
  @param value current value
  @param config
  - withArrays create arrays instead of object when nextKey is a number and key has no value in the current base
  - sameValue use the same value for each element
  @returns {*} a new instance of the given level