The optional chaining mechanism (?.) was introduced in JavaScript for convenient and safe access to properties and methods of objects that may not be defined. In TypeScript, it has become especially useful as it helps avoid runtime errors related to accessing properties or methods of undefined or null.
Before the advent of optional chaining, developers had to manually check the existence of each level of object nesting, making the code long and hard to read:
if (obj && obj.a && obj.a.b) { // ... }
Accessing nested properties on an undefined object can lead to a runtime error: Cannot read property 'x' of undefined. Additionally, long chains of checks complicate code maintenance and readability.
Optional chaining (?.) allows accessing nested properties, methods, or array elements, automatically returning undefined if any part of the chain is null or undefined.
Example:
interface User { name: string; address?: { city?: string; }; } const user: User = { name: 'Ivan' }; console.log(user.address?.city); // undefined
Key features:
T | undefined, which is accounted for by the TypeScript compiler, helping to avoid errors.Can optional chaining be used on the left side of the assignment operator? For example: user.address?.city = 'Moscow'?
No, optional chaining cannot be used in the left expression of an assignment; this will result in a compilation error. Optional chaining works only for reading, not for writing.
Can optional chaining be used to call a method if the object itself may be undefined? For example: user?.logInfo()?
Yes, if the object up to the method call can be undefined/null, then calling user?.logInfo() will not throw an error and will simply return undefined if user is not defined.
user?.logInfo(); // if user is defined, logInfo will be called, otherwise nothing happens
What is the difference between optional chaining and the '&&' operator in the old style, for example: user && user.address && user.address.city?
Optional chaining is shorter, works for all types (including methods and arrays), and TypeScript accounts for it during type checking. Importantly, when using the '&&' operator, you might accidentally get a nested value instead of true/false or undefined. Optional chaining guarantees that you get either the expected type or undefined, which is accounted for in type inference.
The code uses long optional chaining chains even where, according to business logic, the variables are always defined:
order?.customer?.address?.city = 'London';
Pros:
Cons:
Optional chaining is used only when working with external data or in places where values may genuinely be undefined:
const city = apiResponse?.info?.location?.city || 'Unknown';
Pros:
Cons: