JavaScript Snippet
JavaScript Optional Chaining (?.)
Stop crashing on null and undefined. Write shorter, safer code with the optional chaining operator.
Last updated: October 2026
Quick answer: Use ?. to safely access nested properties. If any value in the chain is null or undefined, the expression short-circuits and returns undefined instead of throwing an error. Combine with ?? to provide a default value. It only catches nullish values — not 0, '', or false [citation:5][citation:11].
🎬 Interactive Live Demo
Toggle between a complete user object and an incomplete one to see how optional chaining prevents crashes.
💡 Click the buttons to switch users. Watch the unsafe version throw a TypeError while the safe version returns undefined.
The Problem: Nested Access Crashes
Accessing a property on null or undefined throws a TypeError. When working with API responses, optional fields, or user input, this happens constantly:
const user = { name: "Alice", address: null };
// 💥 TypeError: Cannot read properties of null (reading 'city')
const city = user.address.city;
The old workaround was verbose and error-prone:
// The "safe" old way — verbose and doesn't handle all cases
const city = user.address && user.address.city;
This works for null and undefined, but has a subtle bug: if user.address is 0 or '' (valid but falsy), it incorrectly returns 0 or '' instead of checking deeper [citation:11].
The Solution: Optional Chaining
The ?. operator checks if the value before it is null or undefined. If so, it short-circuits and returns undefined instead of crashing [citation:5][citation:15]:
const user = { name: "Alice", address: null };
const city = user?.address?.city;
// → undefined (no crash)
The chain short-circuits at the first nullish value. In this case, user.address is null, so the entire expression returns undefined immediately — .city is never evaluated [citation:1].
Long Short-Circuiting
The short-circuit skips the entire chain, not just the immediate property [citation:1]:
const data = {
user: {
profile: null
}
};
// If user.profile is null, the whole chain returns undefined
const name = data.user?.profile?.name?.firstName;
// → undefined (not an error)
This is called "long short-circuiting" — once a nullish value is found, everything to the right is skipped.
Optional Chaining with Function Calls
Use ?.() to call a method that might not exist [citation:11][citation:15]:
const api = {
getUser: () => ({ name: "Alice" })
};
// Without optional chaining — crashes if getUser is missing
const user1 = api.getUser();
// With optional chaining — returns undefined if getUser is missing
const user2 = api.getUser?.();
const user3 = api.missingMethod?.(); ; // undefined, no crash
Important: ?. only guards against the method not existing. If the property exists but isn't a function, it still throws a TypeError. And if the parent object itself is null, you need ?. on the parent too: someInterface?.customMethod?.() [citation:15].
Combining with Nullish Coalescing (??)
Optional chaining pairs perfectly with ?? to provide defaults. Use ?? instead of || because || triggers on any falsy value (including 0, '', false) [citation:2][citation:6]:
const settings = {
animationDuration: 0,
headerText: ""
};
// ❌ || returns the default for 0 and ""
const duration1 = settings.animationDuration || 300; // → 300
const header1 = settings.headerText || "Hello"; // → "Hello"
// ✅ ?? only defaults for null/undefined
const duration2 = settings.animationDuration ?? 300; // → 0
const header2 = settings.headerText ?? "Hello"; // → ""
The combination is powerful for real-world data:
const city = user?.address?.city ?? "Unknown";
// If user or address or city is nullish, returns "Unknown"
🎯 Optional Chaining vs Logical AND (&&)
| Value | a && a.b | a?.b |
|---|---|---|
a = { b: 1 } |
1 |
1 |
a = null |
null |
undefined |
a = 0 |
0 (wrong!) |
undefined (correct) |
a = "" |
"" (wrong!) |
undefined (correct) |
&& short-circuits on any falsy value. ?. only short-circuits on null and undefined. This makes optional chaining safer for values like 0 and '' that are valid but falsy [citation:11].
⚠️ Common Mistakes
- Using
?.to silence TypeScript errors. If a value should always exist, let the error surface. Hiding it with?.makes debugging harder later [citation:13]. - Confusing
?.with??.?.is for property access.??is for default values. They solve different problems. - Expecting
?.to catch non-nullish errors. If a property exists but isn't a function,?.still throws. If a variable is undeclared,?.still throws ReferenceError [citation:15]. - Using
?.on the root object without declaring it.undeclaredVar?.propthrows a ReferenceError. Optional chaining can't protect against undeclared variables [citation:15]. - Overusing it everywhere. If your data model expects a value, use it. Reserve
?.for genuinely optional fields or external data.
❓ Frequently Asked Questions
What is optional chaining in JavaScript?
Optional chaining (?.) is a JavaScript operator that lets you access deeply nested properties without explicitly checking if each reference is null or undefined. If any reference is nullish, the entire expression short-circuits and returns undefined instead of throwing an error.
What is the difference between ?. and &&?
The && operator short-circuits on any falsy value (including 0, '', false), while ?. only short-circuits on null and undefined. This makes optional chaining safer for values like 0 or empty strings that are valid but falsy.
When should I NOT use optional chaining?
Don't use optional chaining to silence TypeScript errors or hide bugs where a value should always exist. If a value is genuinely required, let the error surface so you can fix the real problem.
Can I use optional chaining with function calls?
Yes. Use ?.() to call a method that may not exist. For example, someObject.method?.() returns undefined instead of throwing if the method is missing. If the property exists but isn't a function, it still throws a TypeError.
Is optional chaining supported in all browsers?
Yes. Optional chaining has been widely available across all modern browsers since 2020. It is part of the ES2020 specification and is supported in Node.js 14+ as well.