Skip to content

Instantly share code, notes, and snippets.

@xialvjun
Last active February 23, 2021 18:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xialvjun/6c23f0cd278e1ab81226b1b32a1af1bf to your computer and use it in GitHub Desktop.
Save xialvjun/6c23f0cd278e1ab81226b1b32a1af1bf to your computer and use it in GitHub Desktop.
immutable version of lodash/set
// https://github.com/lodash/lodash/issues/1696
import {clone, setWith, curry} from 'lodash/fp';
// export const setIn = curry((path, value, obj) =>
// setWith(clone, path, value, clone(obj)),
// );
export const setIn = curry((obj, path, value) =>
setWith(clone, path, value, clone(obj)),
);
// https://github.com/lodash/lodash/issues/1696#issuecomment-353016126
// f you're using TypeScript, you should consider utilizing some standalone typing-aware "immutable set" library,
// like monolite(https://github.com/kube/monolite) or immutable-assign(https://github.com/engineforce/ImmutableAssign).
// ! 上面的 setIn 会有问题:在遇到 setIn({ a: { b: 1, c: null }, d: "xxx" }, 'a.c.e', 2) => 对象未发生变化,即它无法影响 null
// 于是自己写了一个 setpath
export const setpath = (obj, path, value) => {
const paths = path.split(/[\.\[\]\'\"]/g).map(s => parseInt(s) || s.trim()).filter(v => v!=='');
function set(obj, paths, value) {
if (paths.length === 0) {
return value;
}
if (paths.length === 1) {
const paths_0 = paths[0];
if (paths_0 > -1) {
const clone = (obj || []).slice();
clone[paths_0] = value;
return clone;
}
return Object.assign({}, obj, { [paths_0 + '']: value });
}
const tail = set(get(obj, paths.slice(0, -1)), paths.slice(-1), value);
return set(obj, paths.slice(0, -1), tail);
}
return set(obj, paths, value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment