What is the ?. operator (optional chaining) in TypeScript

avatar
Borislav Hadzhiev

Last updated: Feb 26, 2024
3 min

banner

# The optional chaining ?. operator in TypeScript

The question mark dot (?.) syntax is called optional chaining in TypeScript and is like using dot notation to access a nested property of an object, but instead of causing an error if the reference is nullish, it short-circuits returning undefined.

index.ts
type Person = { address?: { country?: string; }; name?: { first?: string; }; }; const person: Person = { address: { country: 'Chile', }, }; console.log(person.address?.country); // ๐Ÿ‘‰๏ธ "Chile" console.log(person.name?.first); // ๐Ÿ‘‰๏ธ undefined

optional chaining in typescript

The code for this article is available on GitHub

We created a type where the address and name properties are optional.

Most commonly you'll be fetching this data from a database or reading it from a file, where some of the properties might not have a value.

The first console.log statement uses the optional chaining (?.) operator to access the address.country property on the person object.

App.js
const person: Person = { address: { country: 'Chile', }, }; console.log(person.address?.country); // ๐Ÿ‘‰๏ธ "Chile"

The address.country property exists on the person object, so its value gets logged to the console.

The second example uses the optional chaining (?.) operator to access the name.first property on the person object.

However, the property doesn't exist on the object, so the optional chaining (?.) operator returns undefined.

App.js
const person: Person = { address: { country: 'Chile', }, }; console.log(person.name?.first); // ๐Ÿ‘‰๏ธ undefined
Whenever we try to access a property with a nullish (null or undefined) reference, the optional chaining operator (?.) short-circuits returning undefined instead of throwing an error.

If we didn't use the optional chaining (?.) operator, we would have gotten an error because we're trying to access a property on an undefined value.

index.ts
type Person = { address?: { country?: string; }; name?: { first?: string; }; }; const person: Person = { address: { country: 'Chile', }, }; // โ›”๏ธ ERROR: Cannot read properties of undefined (reading 'first') console.log(person.name.first); // ๐Ÿ‘‰๏ธ undefined
The code for this article is available on GitHub

We didn't use the optional chaining (?.) operator to short-circuit in case the name property was not set, so an error occurred.

# Optional chaining (?.) vs logical AND (&&) operator

You might have used the logical AND (&&) operator to get around this in the past.

index.ts
type Person = { address?: { country?: string; }; name?: { first?: string; }; }; const person: Person = { address: { country: 'Chile', }, }; console.log(person.name && person.name.first); // ๐Ÿ‘‰๏ธ undefined

optional chaining vs logical and

The code for this article is available on GitHub

We used the logical AND (&&) operator to check if accessing the name property on the person object returns a truthy value.

If it does, we try to access the first property on the name object.

This is a bit different than using optional chaining because it checks if the reference is truthy, whereas the optional chaining (?.) operator checks that the reference is not null or undefined.

# Using optional chaining to access array indexes

The optional chaining operator can also be used to access an array element at a specific index or short-circuit if the reference is null or undefined.

index.ts
type Person = { numbers?: { low?: number[]; }; }; const person: Person = {}; console.log(person.numbers?.low?.[0]); // ๐Ÿ‘‰๏ธ undefined

using optional chaining to access array indexes

The code for this article is available on GitHub

The low property could be undefined, so trying to access the array element at index 0 on an undefined value would throw an error unless we use the optional chaining (?.) operator to short-circuit if the reference is undefined.

If the property is populated on the object, the optional chaining operator (?.) returns the specified value in the array.

index.ts
type Person = { numbers?: { low?: number[]; }; }; const person: Person = { numbers: { low: [1, 2, 3], }, }; console.log(person.numbers?.low?.[0]); // ๐Ÿ‘‰๏ธ 1

# Using the optional chaining operator with function parameters

The optional chaining (?.) operator can also be used to call a function if its value is not equal to null or undefined.

index.ts
function logger(callback?: (msg: string) => void) { callback?.('hello'); } logger(console.log); // ๐Ÿ‘‰๏ธ "hello"

using optional chaining with function parameters

The code for this article is available on GitHub

Trying to call the callback parameter would cause an error if it isn't provided, so we used the optional chaining (?.) operator to check if the reference is not null or undefined before calling the function.

If the parameter is not provided, the operator will just short-circuit returning undefined instead of calling the function.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev