Skip to content

Instantly share code, notes, and snippets.

@ttmarek
Created March 9, 2017 04:28
Show Gist options
  • Save ttmarek/530f4757f17598b324c8d74d1676e074 to your computer and use it in GitHub Desktop.
Save ttmarek/530f4757f17598b324c8d74d1676e074 to your computer and use it in GitHub Desktop.
A function for deeply setting values
function set(obj, path, value) {
const clone = Object.assign({}, obj);
const keys = path.split('.');
const lastKey = keys.pop();
// --------------------------------------------------
if (keys.length === 0) {
clone[lastKey] = value;
return clone;
}
// --------------------------------------------------
const firstKey = keys.shift();
if (clone[firstKey] === undefined) {
clone[firstKey] = {};
}
const secondToLastKeyRef = keys.reduce((keyRef, key) => {
if (keyRef[key] === undefined) {
keyRef[key] = {};
}
return keyRef[key];
}, clone[firstKey]);
secondToLastKeyRef[lastKey] = value;
return clone;
}
// TESTS
describe('set(obj, path, value)', () => {
it('returns an array with the path set to value', () => {
expect(set({}, 'test', 'some string')).toEqual({ test: 'some string' });
});
it('works with objects', () => {
expect(set({}, 'test', { hey: 1 })).toEqual({ test: { hey: 1 } });
});
it('works when the object is non-empty', () => {
const obj = { hello: 'world' };
expect(set(obj, 'test', false)).toEqual({
hello: 'world',
test: false,
});
});
it('works with deeply nested values', () => {
const obj = { lvl1: { lvl2: { lvl3: {} } } };
expect(set(obj, 'lvl1.lvl2.lvl3.lvl4', 'hi')).toEqual(
{ lvl1: { lvl2: { lvl3: { lvl4: 'hi' } } } }
);
});
it('creates deeply nested objects when needed', () => {
expect(set({}, 'lvl1.lvl2.lvl3.lvl4', 'hi')).toEqual(
{ lvl1: { lvl2: { lvl3: { lvl4: 'hi' } } } }
);
});
it('does not mutate the object passed in', () => {
const obj = { hello: 'world' };
set(obj, 'test', false);
expect(obj).toEqual({ hello: 'world' });
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment