Using ‘?’ (Optional) Operator in TypeScript

Updated: January 8, 2024 By: Guest Contributor Post a comment

Introduction

TypeScript brings strong typing to JavaScript, including the capability to mark certain object properties or function parameters as optional. The optional chaining operator ‘?’ provides a powerful way to handle undefined or null values without constantly checking for their presence. This tutorial guides you through various use cases with simple to advanced code examples.

Understanding Optional Chaining

In TypeScript, you can use the optional chaining operator ‘?’ to safely access deeply nested properties, methods, or functions without having to validate each reference along the way.

interface User {
    id: number;
    name: string;
    address?: {
        street: string;
        city: string;
        zipCode?: string;
    };
}

const user: User = {
    id: 1,
    name: 'John Doe'
};

console.log(user.address?.city); // Output: undefined

Optional Chaining with Functions

You can also use the optional chaining operator when calling functions which may or may not be defined.

function getUser() {
    // Imagine fetching user from an API
    return null; // or a user object
}

const userCity = getUser()?.address?.city;
console.log(userCity); // Output: undefined if getUser returns null

Combining with Nullish Coalescing

TypeScript also offers the nullish coalescing operator ‘??’ which you can combine with optional chaining to provide a default value when dealing with null or undefined.

const userZipCode = user.address?.zipCode ?? 'No Zip Code';
console.log(userZipCode); // Output: 'No Zip Code'

Advanced Use Cases

Optional chaining can also be used in more complex scenarios, such as dynamic property access, optional callback functions, or with arrays.

interface UserOptions {
    onSuccess?: () => void;
    onError?: (error: string) => void;
}

function processUserAction(options: UserOptions) {
    // Process something...
    if (/* some condition */) {
        options.onSuccess?.();
    } else {
        options.onError?.('An error occurred');
    }
}

processUserAction({ 
    onError: (message) => console.error(message) 
});

You can use the operator to check for the existence of an element in array before accessing its properties.

const users: User[] = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Doe', address: { street: 'Main', city: 'Downtown'} }];

const firstUserName = users[0]?.name;
console.log(firstUserName); // Output: 'John Doe'

Gotchas and Limitations

While optional chaining is useful, it also comes with limitations. Misusing it may mask potential bugs or lead to unexpected behaviors.

Conclusion

The ‘?’ optional chaining operator is a valuable tool for simplifying and safeguarding property access in TypeScript. It is most effective when used judiciously, with a good understanding of the data structures you’re working with. As with any powerful feature, care should be taken not to overuse it, which could obscure code logic or intentions.