Conditionally Add Properties to Arrays and Objects in Javascript

I was recently creating a UI component, which was nothing more than a slideable drawer. This drawer was a function, and when opened needed to created a context object. One of the interesting things I did is found a way to mount a view app to this modal and unmount the vue app when it was removed from the DOM, but I didn't always need a vue app. This led me to find a way to conditionally add a property to the context object in the case it existed. Here is a super simplified example of how you can conditionally add properties or values to arrays or objects.

Now to understand this you may to need to do a quick review on short circuiting.

Conditionally Add a Property to an Object

JavaScript
const a = true
const b = false

const obj = {
  ...(a && { name: 'john' }),
  ...(b && { name: 'david' })
}

console.log(obj)
// { name: 'john' }

// lets try this again but modify obj a bit

const obj = {
  ...(a && { name: 'john' }),
  ...(a && { name: 'david' })
}

console.log(obj)
// this logs { name: 'david' } because the objects merge

const obj = {
  ...(true && { name: 'david' }),
  ...(true && { age: 30 })
}

// this will output { name: 'david', age: 30 }

Conditionally Add a Value to an Array

JavaScript
const someTruthyValue = true
const someFalsyValue = ''

const arr = [
  ...(someTruthyValue && ['a']),
  ...(someFalsyValue && ['b'])
]

console.log(arr)
// ['a']

Here is a quick side by side comparison:

JavaScript
const someTruthyValue = true
const someFalsyValue = ''

const obj = {
  ...(someTruthyValue && { name: 'a' }),
  ...(someFalsyValue && { name: 'b' })
}

const arr = [
  ...(someTruthyValue &&  ['a']),
  ...(someFalsyValue && ['b'])
]

Note that you can write the above code block like this without the parenthesis but you should always strive for code readability.

JavaScript
const someTruthyValue = true
const someFalsyValue = ''

const obj = {
  ...someTruthyValue && { name: 'a' },
  ...someFalsyValue && { name: 'b' }
}

const arr = [
  ...someTruthyValue &&  ['a'],
  ...someFalsyValue && ['b']
]

Here falsy value is an empty string which can be spread, but the below code would fail because false cannot be spread out

JavaScript
const someTruthyValue = true
const someFalsyValue = false

const obj = {
  ...someTruthyValue && { name: 'a' },
  ...someFalsyValue && { name: 'b' }
}

const arr = [
  ...someTruthyValue &&  ['a'],
  ...someFalsyValue && ['b']
]

In this case we need to make sure in the case that the array has a falsy value that cannot be spread we cover that case with the ternary operator

JavaScript
const someTruthyValue = true
const someFalsyValue = false

const obj = {
  ...someTruthyValue && { name: 'a' },
  ...someFalsyValue && { name: 'b' }
}

const arr = [
  ...someTruthyValue ? ['a'] :  [],
  ...someFalsyValue ? ['b'] : []
]

Conditional properties can also be nested.

JavaScript
const showAge = true
const showId = false
const showUserDetails = true

const user = {
  email: 'test@gmail.com',
  ...(showUserDetails && {
    name: 'david',
    ...(showAge && { age: 29 }),
    ...(showId && { id: 1 })
  })
}

// { name: 'david', age: 29}

/**
 * here showId is true
 */

const showAge = true
const showId = true
const showUserDetails = true

const user = {
  email: 'test@gmail.com',
  ...(showUserDetails && {
    name: 'david',
    ...(showAge && { age: 29 }),
    ...(showId && { id: 1 })
  })
}

// { name: 'david', age: 29, id: 1}

This last example seems a bit complicated but it is a good excercise. Pay close attention to the code and notice that it does look long and complex but it just takes the simple concepts from above and reuses them.

JavaScript
const x = true
const y = false

const obj = {
    foo: 'foo',
    bar: [
        ...x ? [{ id: 1 }] : [],
        ...y ? [{ id: 2 }] : [],
        { id: 3 }
    ],
    ...(x && { 
        baz: [
            ...x ? ['a'] : [],
            'b',
            ...y ? ['c'] : []
        ]
    })
}