TypeScript Optional Chaining

Optional Chaining is a safe way to access properties in TypeScript and JavaScript.

It allows developers to safely access nested object properties in a chained-call manner. When any property in the access path is null or undefined, the entire expression short-circuits and returns undefined without throwing an error.

This greatly simplifies code for accessing deeply nested object properties.


SVG Diagram: How Optional Chaining Works Background Title How Optional Chaining Works Left side: Traditional approach Traditional approach (verbose) // Requires multiple levels of checks var city = user && user.address && user.address.city; Error-prone and redundant code Arrow Simplification Right side: Optional chaining approach Optional chaining approach (concise) // Done in one line var city = user ?.address ?.city; Safe and concise, with automatic short-circuiting Bottom part: Three usages Three forms of optional chaining Usage 1 obj?.prop — property access Usage 2 arr?. Usage 3 obj?.method() — method call Arrow marker

Why Do We Need Optional Chaining?

In JavaScript/TypeScript development, we often need to access deeply nested object properties.

The traditional approach requires checking each level for the existence of properties. This not only makes code verbose, but can also easily miss checks and cause runtime errors.

Concept explanation:The core of optional chaining is "short-circuit evaluation". When the value of a property in the chain is null or undefined, the entire expression immediately returns undefined without continuing to access subsequent properties.


Basic Syntax

Use?.operator to safely access properties that may not exist.

Compared with the traditional && chained checks, optional chaining syntax is more concise and intuitive.

Example

// Define a nested user object
// Contains name and address info, and the address has a city
var user = {
    name: "EXAMPLE",
    address: {
        city: "Beijing"
    }
};

// Traditional approach: use && to check each level
// This approach is verbose and easy to miss checks
var city1 = user && user.address && user.address.city;

// Optional chaining approach: use the ?. operator
// If any level is null or undefined, directly return undefined
var city2 = user?.address?.city;

console.log("Traditional approach: " + city1);
console.log("Optional chaining: " + city2);

Output:

传统方式: Beijing
可选链: Beijing

Tip:When the object property exists, both approaches produce the same result. But the optional chaining code is more concise and readable.


Handling Non-existent Properties

When a property in the access path does not exist, optional chaining safely returns undefined without throwing an error.

This is especially useful for handling data from APIs or user form input.

Example

// Define an incomplete user object
// Only has the name property, no address property
var user = {
    name: "EXAMPLE"
    // The address property does not exist
};

// Use optional chaining to access deep properties
// user.address is undefined, so city is also undefined
var city = user?.address?.city;

// Access even deeper nested properties
// Even if country does not exist, it still returns undefined without an error
var country = user?.address?.country?.name;

console.log("City: " + city);
console.log("Country: " + country);

Output:

City: undefined
国家: undefined

Note:Optional chaining only returns undefined during property access; it does not create new objects or properties.


Combining Optional Chaining with Arrays

Optional chaining can be combined with array index access to safely access elements in an array.

Use?.[index]syntax to return undefined when an array element does not exist.

does not exist (the array only has 2 elements), returns undefined

// Define an array of users
var users = [
    { name: "Alice" },
    { name: "Bob" }
];

// Safely access the name of the first element in the array
// users?.
var firstUser = users?.[0]?.name;

// Safely access a non-existent element in the array
// users?.
var tenthUser = users?.[9]?.name;

console.log("First user: " + firstUser);
console.log("Tenth user: " + tenthUser);

Output:

第一个用户: Alice
第十个用户: undefined

Explanation:?.[index]and?.The difference is that the former is used for arrays, and the latter for object properties.


Optional Chaining and Method Calls

Optional chaining can be used to safely call methods that may not exist.

Use?.()syntax: if the method does not exist, it returns undefined without throwing an error.

Example

// Define a user object containing a name and a greet method
var user = {
    name: "Alice",
    // Define a greeting method
    greet: function() {
        return "Hello, " + this.name;
    }
};

// Safely call an existing method
// user.greet exists, call it normally and return the result
var message1 = user.greet?.();

// Safely call a non-existent method
// user.sayHello does not exist, returns undefined without an error
var message2 = user.sayHello?.();

console.log("greet: " + message1);
console.log("sayHello: " + message2);

Output:

greet: Hello, Alice
sayHello: undefined

Use cases:This is especially useful when dealing with optional callback functions or event handlers.


Optional Chaining Assignment

Optional chaining can also be used in assignment operations, but you need to be aware of its behavior.

Optional chaining assignment only modifies an existing path; it does not automatically create intermediate objects.

Example

// Define a simple user object
var user = {
    name: "Alice"
};

// Try to use optional chaining assignment
// user?.address does not exist, so the entire assignment is skipped
// The user object remains unchanged
user?.address?.city = "Beijing";

console.log("User: " + JSON.stringify(user));

Output:

User: {"name":"Alice"}

Note:Optional chaining assignment cannot be used to create new properties. If you need to create nested objects, you should use the traditional approach to create intermediate objects first.


Nullish Coalescing and Optional Chaining

Optional chaining is often used with the nullish coalescing operator??in combination.

This combination can provide default values when properties do not exist, making the code more robust.

Example

// Define an incomplete user object
var user = {
    name: "Alice"
    // address does not exist
};

// Optional chaining + nullish coalescing: use default value when city is null or undefined
var city = user?.address?.city ?? "Unknown city";

console.log("City: " + city);

// Comparison: verbose traditional approach
var country = user && user.address && user.address.country
    ? user.address.country
    : "Unknown country";

console.log("Country: " + country);

Output:

City: Unknown City
Country: Unknown Country

Explanation:??only uses the default value when the value is null or undefined, whereas||will also use the default value when the value is falsy (0, "", false). When dealing with numbers or strings, you should prefer to use??。


Notes

  • Short-circuit evaluation:Optional chaining immediately returns when it encounters null or undefined, and does not continue to access subsequent properties.
  • Cannot create properties:Optional chaining assignment does not automatically create intermediate objects.
  • Combine with nullish coalescing:It is recommended to always use??to provide default values, and use less||
  • Performance considerations:Although optional chaining is safer, direct access has better performance when the property is guaranteed to exist.

Suggestion:In actual development, for properties from external data (such as API responses, user input), prefer optional chaining for safe access.


Summary

Optional chaining is an important feature in modern JavaScript/TypeScript for handling nested objects.

  • ?.:Safely access object properties
  • ?.[index]:Safely access array elements
  • ?.():Safely call methods that may not exist
  • ??:Provide default values to handle undefined cases

Best practices:Always use optional chaining for deep property access that may not exist. Combined with the nullish coalescing operator, you can write code that is both safe and concise.

Other extensions