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); // undefinedIf 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); // undefinedSquare 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?.()); // undefinedThe 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 setCommon 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); // 0A 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.