What is the ?. operator in TypeScript

avatar

Borislav Hadzhiev

Sun Feb 13 20223 min read

banner

Photo by Meiying Ng

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

We created a type where the 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.

Because the address.country property exists on the person object, 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, but because the property does not exist on the object, the optional chaining (?.) operator returns undefined.

Whenever we try to access a property with a nullish (null or undefined) reference, the optional chaining operator (?.) short-circuits returningundefined instead of throwing an error.

Had we not used the optional chaining operator, we would get 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

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

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

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 can 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.

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

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 specific 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

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"

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 would just short-circuit returning undefined instead of calling the function.

Use the search field on my Home Page to filter through my more than 1,000 articles.