Optional Chaining and Nullish Coalescing
?. stops a property lookup safely at the first null or undefined instead of throwing; ?? picks a default only for null or undefined.
Loading visual…
Definition
Optional chaining, `?.`, checks whether the value to its left is `null` or `undefined` before continuing the lookup. If it is, the whole expression short-circuits to `undefined` immediately, no error is thrown, and nothing further to the right is evaluated. If it is not, the chain continues as a normal property access or method call. This makes it safe to read a deeply nested path like `user?.address?.city` even when `address` might not exist, instead of writing a chain of manual `&&` checks or a try/catch. Nullish coalescing, `??`, returns its right-hand side only when the left-hand side is `null` or `undefined`, and returns the left-hand side unchanged for any other value, including falsy ones like `0`, `""`, `false`, and `NaN`. This is the key difference from `||`, which falls through to its right-hand side for any falsy value. `0 ?? 5` is `0`, but `0 || 5` is `5`. The two operators are often combined: `user?.settings?.volume ?? 100` safely reads a possibly-missing setting and only substitutes a default when it is genuinely absent.
Examples
const user = { address: null };
user.address.city; // TypeError: Cannot read properties of null
user?.address?.city; // undefined, no errorOptional chaining stops the lookup the moment it hits null, returning undefined instead of throwing.
0 ?? 5; // 0 (0 is not null/undefined)
0 || 5; // 5 (0 is falsy)
"" ?? "x"; // ""
null ?? "x"; // "x"?? only falls back for null or undefined; || falls back for any falsy value, which is why 0 and "" behave differently between the two.
const settings = { volume: 0 };
const volume = settings?.volume ?? 100;
// 0, not 100Even though 0 is falsy, ?? treats it as a present value because it is not null or undefined, so the real setting wins over the default.
Where you see this
- Safely reading a nested API field that might be missing, like response?.data?.user?.email.
- Calling an optional callback only if it was provided: onSave?.().
- Applying a default for a config value that may legitimately be 0 or an empty string, without accidentally overwriting it.
- Replacing long defensive chains of if (a && a.b && a.b.c) checks with a single optional chain.