Search code examples
javascriptnode.jstypescriptecmascript-6lodash

How to tell where an object value is undefined?


Below have I a very simple function, which I type check at compile and runtime, but I would to also rumtime check all the keys result in a value, and if it doesn't, then prompt where it broke.

The only solution I can think of is

assert(typeof db[customer] !== undefined);
assert(typeof db[customer].offers !== undefined);
assert(typeof db[customer].offers[offerId] !== undefined);
assert(typeof db[customer].offers[offerId][key] !== undefined);

but it is a lot of typing. I expected lodash would have a solution for this problem, but doesn't seem to be the case.

If I do

db?[customer]?.offers?[offerId]?[key] = value;

then I don't know where it returned undefined.

import assert from 'assert';

export function setPropertyOffer(
  db: Record<string, any>,
  customer: number,
  offerId: number,
  key: string,
  value: number | string,
) {
  assert(typeof db === 'object');
  assert(typeof customer === 'number');
  assert(typeof offerId === 'number');
  assert(typeof key === 'string');
  assert(typeof value === 'string' || typeof value === 'number');

  db[customer].offers[offerId][key] = value;
}

Solution

  • You can use a function to help you decide. It takes an object, and an array (or arguments) of keys to get value.

    var obj = [{
      "category1": {
        nested: {
          a: 'string',
          b: [69, 13, 15]
        }
      },
      "category2": "2",
    }];
    
    console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 2))
    // print 15
    
    console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 4))
    // print undefined at key 4
    
    function where_undefined(obj) {
      var args = Array.prototype.slice.call(arguments)
      args.shift();
      while (args.length) {
        var arg = args.shift();
        if (obj[arg] === undefined) {
          console.log("undefined at key " + arg);
          break;
        } else {
          obj = obj[arg];
        }
      }
      return obj;
    }