Home Reference Source

ts_temp/object/pathSetBy.js

import curryN from '../function/curryN';
import isObject from '../is/object';
import isNumber from '../is/number';
import has from './has';
import assign from '../assign';
/**
 * Returns the result of "setting" the portion of the given data structure
 * focused by the given paths to the result of `fn` call.
 *
 * **Note:** If property in the object is equal to value by reference then function
 * just returns object without changes
 *
 * @param {[String]} paths
 * @param {Function} fn
 * @param {Object} obj
 * @return {Object}
 * @example
 *
 *      pathSetBy(['a', 'b'], x => x+1, {a: { b:1 }}) // => { a: { b: 2 } }
 */
export default curryN(3, (paths = [], fn, obj = {}) => {
    const n = paths.length - 1;
    const result = assign(obj);
    const key = paths[n];
    let val = result;
    let v;
    for (let i = 0; i < n; i++) {
        v = val[paths[i]];
        if (isObject(v)) {
            v = assign(v);
        }
        else {
            v = isNumber(paths[i + 1]) ? [] : {};
        }
        val[paths[i]] = v;
        val = v;
    }
    const res = fn(val[key], paths, obj);
    if (has(key, val) && val[key] === res) {
        return obj;
    }
    val[key] = res;
    return result;
});