BlogJavaScript

Conditionally adding a property to an object in JavaScript

Written by Codemzy on August 15th, 2022

Here's the conditional object property pattern. It uses the spread syntax (...) to conditionally add a property to an object, or an item to an array. Perfect when you (sometimes) want to add a key to an object.

In my last blog post, I wrote about an interesting pattern for copying an object without a specific property. In this post, we will look at a pattern that does the opposite. Instead of removing properties, we're adding them - but only sometimes!

Here's the pattern I use:

const myObject = {
  ...(isTrue && {someKey: "Some value"}),
};

Ok, so I guess it looks kinda funky, but I use this pattern much more than I expected to (more on that below). And you can do the same thing with arrays too - but notice that the expression changes slightly.

const myArray = [
  ...(isTrue ? ["Some value"] : []),
];

Let's try and figure out how this works!

Creating an object in javascript

First off, I'll mention that I generally use this pattern when creating my objects using object literal syntax.

let myObject = {
  name: "Codemzy",
  isDoing: "coding"
};

This is my favourite way to create objects, and I rarely use new Object() or Object.create() unless I have need to.

Why would you want to conditionally add a property to an object?

Let's say your JavaScript application has users. When a user logs in, you get a user object. Sometimes, users are a member of a team, and you'll want to add a team property.

Or you have a menu object, that represents each of the menu items on your website. You're going to loop over the keys to display the menu. But you need to add some extra menu items for users if they have a special role, like an admin.

Why not just add a false value?

Sometimes, adding a false value works well. In fact, I'd probably say for the team property, it would be a good option.

let myObject = {
  name: "Codemzy",
  isDoing: "coding",
  team: false,
};

But sometimes, you don't want the property there at all. Maybe you use the properties of an object at some stage with Object.keys(myObject) - like in the menu object we just discussed.

And sometimes, I'm creating an object to run a query against a database, and if the value is false, then it just shouldn't be part of my search object. But if it's true, it should be included.

function search(title, type, status) {
  return {
    title: title,
    type: type,
    status: status
  };
};

search("Some Title", false, "active");

This returns:

{ 
  title: "Some Title", 
  type: false,
  status: "active"
}

But if there's no type, we don't want the type property in the search object. Otherwise, when we use the object in the search it will look for type === false - but instead, we want results of any type.

You can find a way to remove the property, or sort it out in your code, or you could just not put the key on your object in the first place. Yes, please!

Conditional adding properties with an if statement

let myObject = {
  name: "Codemzy",
  isDoing: "coding"
};
if (team) {
  myObject.team = team;
};

The problem with this approach is that you add the property after the object is created. That might be ok from a code point of view, but from a readability point of view, at first glance, you might not realise the property is sometimes added.

And what if you have lots of conditional properties to add (or not add as the case may be)? Each condition will need its own if statement. And that could start to look messy and become even harder to follow.

let myObject = {
  name: "Codemzy",
  isDoing: "coding"
};
if (team) {
  myObject.team = team;
};
if (friends) {
  myObject.friends = friends;
};
if (project) {
  myObject.project = project;
};

So let's go back to the original pattern we started this post with. It allows you to add properties conditionally during object creation. Maybe we can call it the conditional object property pattern. Let's look at how it works.

Conditioning adding properties during object creation

const myObject = {
  ...(isTrue && {someKey: "Some value"}),
};

Ok, can we get a better example?

Let's imagine we have a user object, and sometimes we want details of the user's friends, but sometimes you don't need that information. You have a function to get the user object and friends list, and it's something like this...

const getUser = function(username) {
  fetchUser(username).then(function({ user, friends }) {
    return { 
      ...user, 
      friends: friends 
    };
  });
};

Let's pretend this function also contains error handling and some other stuff, that you don't want to duplicate, so you decide to reuse it but sometimes not include the friends property. So you want to add the friends property conditionally.

You don't want to return friends as false - because that's not true. They do have friends - you just don't need to know about them right now.

Here's how you can do that with the conditional object property pattern.

const getUser = function(username, fullInfo) {
  fetchUser(username).then(function({ user, friends }) {
    return { 
      ...user, 
      ...(fullInfo && {friends: friends})
    };
  });
};

Now you can call your function getUser(username, true) for the full details, and getUser(username, false) if you don't need the extra info!

Same pattern for conditionally adding items to arrays

As I mentioned at the start of this post - you can use a very similar pattern for arrays.

const myArray = [
  ...(isTrue ? ["Some value"] : []),
];

The array spread syntax throws an error if you give it a false (which works ok for objects) so instead of an && operator, I use a ternary ? operator instead and either return the value in an array, or a blank array. The returned array is spread ... so the empty array disappears, or our value gets added to the new array.

I've also used this in cases where I have a menu and some of the items are different depending on the user.

const myMenu = [
  "Home",
  "Pricing",
  ...(isLoggedIn ? ["Dashboard"] : ["Log In"]),
  ...(isAdmin ? ["Admin"] : []),
];