Cleaning up your code using optional chaining Javascript

• 3 min read

Optional chaining landed in Chrome 80.

I bet that if you have been writing javascript code you have interacted with such syntax somewhere in your life:


// assuming this our object or data
const car = {
  name: 'BMW',
  engine: {
    model: 2019
  },
}

// when accessing values from an object
// What we all know is:
let numberOfWheels = car.wheels.numberOfWheels
// outputs error: Uncaught TypeError: Cannot read property 'numberOfWheels' of undefined

// so we have to do checks to access the objects values
// using if else
let model
if (car.engine) {
  model = car.engine.model
}
// outputs: 2019
console.log(model)

// which does not exist in our object
let numberOfWheels
if (car.wheels) {
  numberOfWheels = car.wheels.number
}
// outputs: undefined
console.log(numberOfWheels)

// OR

// using logical AND
let model = car.engine && car.engine.model
// outputs: 2019
console.log(model)

let numberOfWheels = car.wheels && car.wheels.numberOfWheels
// outputs: undefined
console.log(numberOfWheels)

Javascript has now introduced optional chaining operator ?. provides a way to simplify accessing values through connected objects when it’s possible that a reference or function may be undefined or null.

Usage of the chaining operator using the same example up there is:


let model = car.engine?.model
// outputs: 2019
console.log(model)

let numberOfWheels = car.wheels?.numberOfWheels
// outputs: undefined

Optional chaining can also be used in calling a method that may not exist in an object. Using optional chaining with function calls causes the expression to automatically return undefined instead of throwing an exception if the method isn’t found.

// if you call the method from an object that does not exist, it will throw an exception
car.create()
// outputs: TypeError: car.create is not a function

// optional chaining handling
car.create?.()
// outputs: undefined

Also when accessing arrays, optional chaining can be used when accessing an item that may not exist:

let arr = []

let item = arr?.[1]
console.log(item)
// outputs: undefined

More Examples

Combining with the nullish coalescing operator

The nullish coalescing operator may be used after optional chaining in order to build a default value when none was found:


const carCountry = car?.country ?? 'Unknown country'
console.log(carCountry)
// outputs: Unknown Unknown country

map function and undefined problem

Suppose you’ve got the following array:

const carModels = [
  { new: 'brand new' },
  { old: 'old car' },
  { new: 'new car' },
  { new: 'Latest model car' },
  { old: 'vintage car' }
]

You want to loop over it to produce a new array containing only those objects with the new property. The map function is your friend and we can do:

const newModels = arr.map(function(element) {
  if (element.new) return element
})

console.log(newModels);
// outputs: [ { new: 'brand new' }, undefined, { new: 'new car' }, { new: 'Latest model car' }, undefined]

So if you try to access property new of newModels[1]:

let car = newModels[1].new
console.log(car)
// outputs error: Uncaught TypeError: Cannot read property 'new' of undefined

// optional chaining solves the problem
let car = newModels[1]?.new

Wrapping Up

As we have seen optional chaining aims to simplify one of the most common patterns in JavaScript: nested property access on objects. Now you write a clean code using optional chaining.

For more examples and reference go to developer.mozilla.org

Thanks for reading, cheers 🥂