object-path-immutable icon indicating copy to clipboard operation
object-path-immutable copied to clipboard

Proposal: Don't assume numbers as array indexes, use brackets [] instead

Open mariocasciaro opened this issue 7 years ago • 2 comments

Now: path.to.array.0 => After: path.to.array[0]

Pros? Cons?

mariocasciaro avatar Feb 08 '18 19:02 mariocasciaro

I like this change, but it is heavily breaking.

I think the string format should conform to this, but the array format should not, IE:

val x = {};
immutable.set(x, ['foo', 0, 'bar'], 'baz') === {
  foo: [
    { bar: 'baz' }
  ],
};

immutable.set(x, 'foo.0.bar', 'baz') === {
  foo: {
    0: { bar: 'baz' };
  };
};

// so:
immutable.set(x, 'foo[0].bar', 'baz') === immutable.set(x, ['foo', 0, 'bar'], 'baz')

Also, what would convention want to be for: 'foo.[0].bar and 'foo[0].bar? I don't mind path throwing for malformed strings when introducing [\d+]

See how lodash handled paths: https://lodash.com/docs/4.17.5#set

c-dante avatar Feb 09 '18 16:02 c-dante

I'm in favor of this change. This could be updated, and then bump the version to a new MAJOR release.

In the meantime I've created my own utility function that uses lodash's toPath-function, to convert the path to an array instead, which this library deals with "correctly".

import _toPath from 'lodash/toPath';
import immutable from 'object-path-immutable';

/**
 * updates a nested property in `object` and returns back the updated object
 * eg. updates formData with `addresses[0].city` to `value`
 * the reason why we have this method, is that when updating the store, we don't want to mutate the object
 * 
 * 1. We are using https://github.com/mariocasciaro/object-path-immutable under the hood
 * 2. We are using lodash's `toPath` function to transform the path, e.g `addresses[0].city` to
 *   `['addresses', 0, 'city']` because `object-path-immutable` have a different way of parsing paths, see issue: 
 *    https://github.com/mariocasciaro/object-path-immutable/issues/27
 */
function getObjectWithoutMutation(object, path, value) {
  const pathAsArray = _toPath(path);
  const newObject = immutable(object).set(pathAsArray, value).value();
  return newObject;
}

This seems to work well for me.

Ping @c-dante and @mariocasciaro .

pudgereyem avatar Sep 03 '19 13:09 pudgereyem