Search code examples
javascriptjsonobjectundefinedeslint

Is using undefined as a value in object definition a good practice?


tl;dr: Is it a good practice to use undefined as a value or should I avoid it and try with another aproach?

I have an object which I use as a schema for my two functions createUser() and updateUser() and based on what values I need, I reconfigure it.

For updateUser() I need to send only the keys user entered in a form so the only way I know of, without changing the structure of the object manually, is to set the values to undefined.

// d is passed as argument

const args = {
  variables: {
    where: {id: "someValue"},
    data: {
      username: d.username || undefined,
      password: d.password || undefined,
      role: d.role || undefined,
    },
  },
};

Now if I have entered only username, my object will be

variables: {
  where: { id: "someValue"}, 
  data: { username: "anotherValue" }
}

I have given it a second thought after ESLint gave me a warning "Unexpected use of undefined."

NOTE I can't send empty values to API. It has to have either value or not send the key at all.


Solution

  • It's difficult to determine what good is and isn't, because it's always all about the needs and preferences of the client and your teammates.

    The very simple and short answer to the question is: yes. undefined is a valid value and if this would be an evidently bad practice, then the language would not allow that value to be assigned. However, it's important to make sure that you do not duplicate your values. Taking a look at this object

    {
      variables: {
        where: {id: "someValue"},
        data: {
          username: d.username || undefined,
          password: d.password || undefined,
          role: d.role || undefined,
        },
      },
    };
    

    we see that you repeat the same idea over and over again. Instead, you would do better to implement something like this:

    function nicify(object) {
        for (var key in object) {
            if (!object[key]) object[key] = undefined;
            else if ((typeof(object[key]) === "object") || (Array.isArray(object[key]))) {
                nicify(object[key]);
            }
        }
    }
    

    the function above recursively does what you wanted to do with your attributes. This will be very helpful if you have many attributes and/or many use-cases. Also, if you consistently have the pattern of having a source object as in your example, then you can implement something like this:

    function fillBySource(object, source) {
        for (var key in source) {
            object[key] = source[key] || undefined;
        }
    }