简体   繁体   中英

Cleaner way to destructure nested objects with defaults?

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['xyz'] into a safe pxyz operation:

 const {'xyz': a = 42} = path({}); const {'xyz': b = 42} = path({x: {}}); const {'xyz': c = 42} = path({x: {z: {}}}); const {'xyz': 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(axyz(42), bxyz(42), cxyz(42), dxyz(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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM