Optional chaining is a powerful feature introduced in TypeScript 3.7. It lets you safely access properties and methods of an object without having to worry about the object being null or undefined. This can help prevent runtime errors and make code more concise and readable.

The Problem

One of the most common problems in programming is accessing properties or methods of an object that might not exist. For example, let’s say we have the following TypeScript code:

type Address =  {
    city: string;
    postcode: string;
}

type Person = {
    name: string;
    age: number;
    address: Address | undefined;
};

We have a person type that may or may not contain some address information. Now let’s make up a function, I want to be able to access that address and use it to send mail to a person:

function sendMail(person: Person) {
    const city = person.address.city; //TS18048: 'person.address' is possibly 'undefined'.
    const postcode = person.address.postcode; //TS18048: 'person.address' is possibly 'undefined'.
}

I’ve instantly ran into a problem. I can’t access the properties, because the address might not exist. In this situation there’s only one level of nesting, but in more complex apps or larger codebases you might run into more complex objects. Imagine trying to access an object like this:


type TooNested = {
    a?: { b?: { c?: { d?: { e?: number } } } };
};

This is where optional chaining steps in. It let’s us sort of “pass down” the undefined part:

function sendMail(person: Person) {
    const city = person.address?.city;
    const postcode = person.address?.postcode;
}

The syntax for optional chaining is a question mark (?). We can use it to indicate that a property or method might not exist, and TypeScript will automatically handle the null or undefined case for us.

Address might be undefined, but if it is, the optional chaining operator lets us just pass that down and make city/postcode undefined.

Functions

Optional chaining can be used with any property or method access, including function calls. For example, if we have a function that might not exist, we can use optional chaining to safely call it without worrying about runtime errors:

const obj = {
  func: () => console.log('Hello!')
};

obj.func?();

If the func property doesn’t exist, TypeScript will simply skip the function call and move on!

Conclusion

Optional chaining is a powerful feature in TypeScript that can help prevent runtime errors and make code more readable and concise. It lets us easily access nested objects and functions without worrying about null or undefined values.

If you’re working with large, complex objects, or dealing with external data sources that might not be well-formed, optional chaining is a feature you’ll definitely want to take advantage of.

If you liked this article, or if you’re having any trouble following along, feel free to leave a comment below!

Avatar photo
👋 Hey, I'm Omari Thompson-Edwards
Hey, I'm Omari! I'm a full-stack developer from the UK. I'm currently looking for graduate and freelance software engineering roles, so if you liked this article, reach out on Twitter at @marile0n

💬 Leave a comment

Your email address will not be published. Required fields are marked *

We will never share your email with anyone else.