Closed oluckyman closed 5 years ago
Good question. This is actually by design. For one, if shades automatically created objects when they didn't exist, it would be harder to catch errors like:
set('adress', 'zip')('1234')(user)
For another, we don't know that creating an object is even the right behavior. Maybe the user wants a Map
, or an Immutable.js Record
. Keeping this flexible enough to handle all of these options would add too much complexity and mess to the API.
Finally, this would be very difficult for the type system to handle.
In terms of workarounds, there's two approaches that are best (in my opinion).
This is the easiest. All you have to do is stop the lens at the last point where you have guaranteed keys:
set('address')({zip: '1234'})(user)
Clean and simple. However, if you had a value at address
with other keys that you wanted to preserve, they would be blown away.
Which brings us to...
null
For this case, you can use the new function fill
(only available on the beta).
> mod('address')(fill({zip: '1234'}))({})
{ address: { zip: '1234' } }
However, this does have a downside. fill
always defaults to the value in the given object, so if the value does have a zip
, then it will be maintained:
> mod('address')(fill({zip: '1234'}))({address: {zip: '4567'})
{ address: { zip: '4567' } }
To fix this, we just have to flip
the order of arguments to fill
:
> mod('address')(flip(fill)({zip: '1234'}))({address: {zip: '4567'})
{ address: { zip: '1234' } }
This approach also merges in keys from both objects in the ways you would want:
> const backfill = flip(fill)
> const user = {address: {zip: '4567', city: 'London'}
> mod('address')(backfill({zip: '1234'}))(user)
{ address: { zip: '1234', city: 'London' } }
Thanks for the awesome lib! I have a question. It's inspired by lodash but
set
fails to create missing objects to accomplish the task:Fails with "Cannot read property 'set' of undefined" Is it by design? How one supposed to handle such situation? This will work, but does not seems elegant at all 🙁