Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Optional chaining and ??

Data often arrives incomplete: a user has no address, an order has no discount. Reading a property of an object that does not exist stops the program with an error. Optional chaining ?. and the ?? operator help you handle such places carefully.

The problem

Reading a property of undefined throws a TypeError. The user below has no address property, so trying to read address.city breaks the program:

const user = { name: 'Anna' };
 
try {
  console.log(user.address.city);
} catch (error) {
  console.log(error.name); // TypeError
}

The ?. operator

Optional chaining ?. checks the value on its left. If it is null or undefined, the whole chain immediately returns undefined instead of an error:

const user = { name: 'Anna' };
 
console.log(user.address?.city); // undefined

If the address does exist, ?. behaves like an ordinary dot.

Long chains

You can put ?. in several places of one chain — wherever a value may be missing:

const order = {
  customer: { name: 'Oleg', address: { city: 'Riga' } },
};
 
console.log(order.customer?.address?.city); // Riga
console.log(order.delivery?.date);          // undefined

Square brackets and method calls

For square brackets write ?.[ ], and for calling a method that may not exist, ?.():

const user = { name: 'Anna', tags: ['admin'] };
 
console.log(user.tags?.[0]); // admin
console.log(user.sayHi?.()); // undefined

The object has no sayHi method, so the call is simply skipped.

A default value: ??

The ?? operator returns the right-hand value when the left one is null or undefined. Together with ?. it gives a fallback for when the data is missing:

const user = { name: 'Anna' };
 
const city = user.address?.city ?? 'city not set';
 
console.log(city); // city not set

Common mistake

People often write || for defaults, but it replaces any falsy value — including 0 and the empty string. ?? replaces only null and undefined:

const settings = { volume: 0 };
 
console.log(settings.volume || 50); // 50
console.log(settings.volume ?? 50); // 0

A volume of 0 is a perfectly valid value, and || lost it. One more tip: do not put ?. everywhere. If a property must be there, let the error show that the data is wrong instead of hiding it behind undefined.

Thanks for reading!

Donate to the site — we work hard for you.