I have a nested object which may have stuff missing:
const unreliableObject = {
id: 10,
nestedObject: { // may be missing
id: 11 // may also be missing
}
}
Now say I want to get the inner id. I can do the following
const { nestedObject: { id: key = -1 } = {key: -1} } = unreliableObject;
console.log(key);
Is there a better way? Something where I'm not defining {key: -1}
twice, nor using an empty object (we have lint rules in place), and I still want to default key in that case.
If you're willing to accept a path notation similar to Lodash's get and the use of a Proxy object then you can turn p['x.y.z']
into a safe p.x.y.z
operation:
const {'x.y.z': a = 42} = path({});
const {'x.y.z': b = 42} = path({x: {}});
const {'x.y.z': c = 42} = path({x: {z: {}}});
const {'x.y.z': d = 42} = path({x: {y: {z: 999}}});
console.log(a, b, c, d);
<script>
const path = obj =>
new Proxy(obj, {
get(o, k) {
const [head, ...tail] = k.split('.');
return tail.length === 0 ?
o[head] :
path(o[head] != null ? o[head] : {})[tail.join('.')];
}
});
</script>
If you're willing to not use destructuring and accept even more Proxy magic, then we could do other crazy things like turning properties into functions!
const p = path(/* some object */);
p.x.y.z(42);
// either the value at 'x.y.z' or 42
const a = path({});
const b = path({x: {}});
const c = path({x: {z: {}}});
const d = path({x: {y: {z: 999}}});
console.log(a.x.y.z(42),
b.x.y.z(42),
c.x.y.z(42),
d.x.y.z(42));
<script>
const path = obj =>
new Proxy(obj, {
get: (o, k) =>
o[k] == null
? path(x => x)
: typeof o[k] === 'object'
? path(o[k])
: () => o[k] });
</script>
This is probably overengineered but I wanted to toy with Proxy anyway ;) Perhaps this helps though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With