object/setPath.jsjavascript
import { cloneContainer, toPath } from '../_internal/path'

/**
 * 按路径设置嵌套属性并返回新对象,输入对象保持不变。
 * @function setPath
 * @memberof module:object
 * @param {Object} object 原对象
 * @param {string|number|Array<string|number>} path 属性路径
 * @param {*} value 要设置的值
 * @returns {Object} 设置后的新对象
 * @throws {TypeError} object 或 path 类型不正确时抛出
 */
function setPath(object, path, value) {
  if (object === null || typeof object !== 'object') throw new TypeError('object must be an object')
  const parts = toPath(path)
  if (parts.length === 0) return object
  const result = cloneContainer(object)
  let target = result
  let source = object
  parts.slice(0, -1).forEach((part, index) => {
    const nextPart = parts[index + 1]
    const existing = source !== null && source !== undefined && typeof source === 'object' ? source[part] : undefined
    const next = existing !== null && typeof existing === 'object' ? cloneContainer(existing) : (/^\d+$/.test(nextPart) ? [] : {})
    target[part] = next
    target = next
    source = existing
  })
  target[parts.at(-1)] = value
  return result
}

export default setPath