Last active
March 17, 2021 19:15
-
-
Save amsterdamharu/659bb39912096e74ba1c8c676948d5d9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const REMOVE = () => REMOVE; | |
const get = (object, path, defaultValue) => { | |
const recur = (current, path, defaultValue) => { | |
if (current === undefined) { | |
return defaultValue; | |
} | |
if (path.length === 0) { | |
return current; | |
} | |
return recur( | |
current[path[0]], | |
path.slice(1), | |
defaultValue | |
); | |
}; | |
return recur(object, path, defaultValue); | |
}; | |
const set = (object, path, callback) => { | |
const setKey = (current, key, value) => { | |
if (Array.isArray(current)) { | |
return value === REMOVE | |
? current.filter((_, i) => key !== i) | |
: current.map((c, i) => (i === key ? value : c)); | |
} | |
return value === REMOVE | |
? Object.entries(current).reduce((result, [k, v]) => { | |
if (k !== key) { | |
result[k] = v; | |
} | |
return result; | |
}, {}) | |
: { ...current, [key]: value }; | |
}; | |
const recur = (current, path, newValue) => { | |
if (path.length === 1) { | |
return setKey(current, path[0], newValue); | |
} | |
return setKey( | |
current, | |
path[0], | |
recur(current[path[0]], path.slice(1), newValue) | |
); | |
}; | |
const oldValue = get(object, path); | |
const newValue = callback(oldValue); | |
if (oldValue === newValue) { | |
return object; | |
} | |
return recur(object, path, newValue); | |
}; | |
const data = { | |
name: [{ hello: 'world', stay: true }, 4], | |
list: [1, 2, 3], | |
}; | |
console.log( | |
'setting nested value', | |
set(data, ['name', 0, 'hello'], () => 'hello world') | |
.name[0].hello | |
); | |
console.log( | |
'doubling nested value', | |
set(data, ['name', 1], x => x * 2).name[1] | |
); | |
console.log( | |
'removing nested value', | |
set(data, ['name', 0, 'hello'], REMOVE).name[0] | |
); | |
console.log( | |
'adding to an array', | |
set(data, ['list'], v => [...v, 4]).list | |
); | |
console.log( | |
'mapping an array', | |
set(data, ['list'], v => v.map(v => v * 8)).list | |
); | |
console.log( | |
'return same reference if nothing changed', | |
set(data, ['list'], x => x) === data | |
); | |
console.log( | |
'data is not mutated', | |
JSON.stringify(data, undefined, 2) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment