What does the optional chaining operator actually do?
It short-circuits the whole chain when it meets a null or a missing value. Instead of throwing, the expression evaluates to the empty value and the rest of the chain is never evaluated.
const response = { data: { user: { name: "Ada" } } };
console.log(response?.data?.user?.name); // "Ada"
console.log(response?.missing?.user?.name); // undefined - no crash
const empty = {};
try {
console.log(empty.data.user.name);
} catch (err) {
console.log("crashed:", err.name); // "TypeError"
}
console.log(empty?.data?.user?.name); // undefinedThe important detail is that the short-circuit happens at the first missing step and skips everything after it. If you wrote response?.data.user.name and the data property were missing, the chain would stop at the question mark and the later property accesses would not run, so no error would occur. The question mark therefore protects the whole expression to its right, not just the single property it sits next to.
Two related points. Optional chaining does not distinguish between null and a missing value; both stop the chain. And you can use it on a function call as well as on a property, so obj.method?.() calls the method only if it exists.
The one thing you cannot do is write an optional chain without an assignment or a call at the end of it. The language requires a chain to end in a reference, a call or an assignment, so you cannot write a bare obj?.prop as a statement. That restriction exists so that the operator cannot be used in a way that would silently swallow a genuine mistake.