DEV Community

Discussion on: 😰 Optional chaining trap !

Collapse
 
devinrhode2 profile image
Devin Rhode • Edited

what do people think of this debugging focused cousin of lodash.get, I call it "safeGet"

if (!window.safeGet) {
    // inspiration: https://dev.to/devinrhode2/comment/fcnp
    // I wish this was a polyfill on Object.prototype but that is just not working..
    // // I guess it's not technically a polyfill until I submit a proposal to tc39...
    // window.customObject_prototype_lookup_defined = true;
    // if (Object.prototype.lookup) {
    //     console.error(
    //         'Object.prototype.lookup is already set to:',
    //         Object.prototype.lookup,
    //         'this is not expected'
    //     );
    // }
    // // eslint-disable-next-line no-extend-native
    // Object.prototype.lookup = function Object_lookup(object, path) {
    //     let object = this;
    window.safeGet = function safeGet(object, path, { returnLastNonNullValue = false }) {
        path = path.split('.');

        let index = 0;
        const length = path.length;
        let currentPath = '';
        let nextBit = '';

        while (object != null && index < length) {
            nextBit = path[index++];
            // eslint-disable-next-line security/detect-object-injection
            if (object[nextBit] != null) {
                currentPath = currentPath + '.' + nextBit;
            } else {
                console.log(
                    'Lookup failed: ' + currentPath + '.' + nextBit + ' is:',
                    // eslint-disable-next-line security/detect-object-injection
                    object[nextBit],
                    currentPath + ' is:',
                    object
                );
            }
            if (returnLastNonNullValue) {
                // eslint-disable-next-line security/detect-object-injection
                if (object[nextBit] != null) {
                    // eslint-disable-next-line security/detect-object-injection
                    object = object[nextBit];
                }
            } else {
                // default lodash.get behavior
                // eslint-disable-next-line security/detect-object-injection
                object = object[nextBit];
            }
        }

        if (index && index == length) {
            // successful lookup
            return object;
        } else {
            // even if we didn't get to end of property path
            // returnLastNonNullValue may be true
            // therefore return object if it's not null
            return object != null ? object : undefined;
        }
    };
}
Collapse
 
devinrhode2 profile image
Devin Rhode • Edited

I wasn't able to add lookup to the Object.prototype because I was getting this error with my CRA v3+CRACO setup...

"Invariant Violation: EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, lookup"

The stack trace was pure webpack hell, did not include it in my google search..

I tried adding it directly in my index.html in a script tag but that didn't fix it. I could, however, delay defining it for 5 seconds via setTimeout and I can then define Object.prototype.lookup

Collapse
 
devinrhode2 profile image
Devin Rhode • Edited

I'd really love this api:
someObject.lookup('some.really.long.property.path') - works essentially just like lodash.get or optional chaining. But what if you want to know why the lookup failed?
just print someObject.lastLookupMsg

As a failsafe, is the last lookup was successful.. this could be set to true (there is no meaningful message for successful lookups)
If the last lookup failed, it COULD just automatically console.log("Lookup failed: some.really.long is:", some.really.long, "some.really is:", some.really);

Maybe there could be a cousin to optional chaining ?. – perhaps ~. Means "tread carefully" and returns the last property lookup that was not undefined/null.

Or perhaps ?. could have a debugging version which does the console.log for you in development only.

Collapse
 
devinrhode2 profile image
Devin Rhode

At the end of the day I think I would prefer to use a simple Object.prototype.lookup method that automatically console.log's the message I described.

Thread Thread
 
devinrhode2 profile image
Devin Rhode • Edited

One issue is that passing an object lookup path as a string results in no syntax highlighting, you probably lose out on a bunch of other potential ide goodies, but from what I know they mostly don't apply to the main use case of check data from the user or from over the wire.