Extend `setIn` with optional support for creating missing path

This commit is contained in:
Jos de Jong 2020-07-26 10:45:56 +02:00
parent b9ceec09e3
commit ad4572d21e
2 changed files with 46 additions and 4 deletions

View File

@ -94,19 +94,35 @@ export function getIn (object, path) {
* @param {Object | Array} object
* @param {Path} path
* @param {*} value
* @param {boolean} [createPath=false]
* If true, `path` will be created when (partly) missing in
* the object. For correctly creating nested Arrays or
* Objects, the function relies on `path` containing a number
* in case of array indexes.
* If false (default), an error will be thrown when the
* path doesn't exist.
* @return {Object | Array} Returns a new, updated object or array
*/
export function setIn (object, path, value) {
export function setIn (object, path, value, createPath = false) {
if (path.length === 0) {
return value
}
const key = path[0]
const updatedValue = setIn(object ? object[key] : undefined, path.slice(1), value, createPath)
if (!isObjectOrArray(object)) {
if (createPath) {
const newObject = typeof key === 'number'
? []
: {}
newObject[key] = updatedValue
return newObject
} else {
throw new Error('Path does not exist')
}
}
const key = path[0]
const updatedValue = setIn(object[key], path.slice(1), value)
return applyProp(object, key, updatedValue)
}

View File

@ -72,6 +72,32 @@ describe('immutabilityHelpers', () => {
assert.throws(() => setIn(obj, ['a', 'b', 'c'], 4), /Path does not exist/)
})
it.only('setIn non existing path with createPath=true', () => {
const obj = {}
assert.deepStrictEqual(setIn(obj, ['a', 'b', 'c'], 4, true), {
a: {
b: {
c: 4
}
}
})
assert.deepStrictEqual(obj, {})
})
it('setIn non existing path with createPath=true and nested array', () => {
const obj = {}
assert.deepStrictEqual(setIn(obj, ['a', 2, 'c'], 4, true), {
a: [
,
,
{ c : 4 }
]
})
assert.deepStrictEqual(obj, {})
})
it('setIn replace value with object should throw an exception', () => {
const obj = {
a: 42,