Last updated: Feb 26, 2024
Reading timeยท3 min

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.
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 address and name properties are optional.
The first console.log statement uses the
optional chaining (?.)
operator to access the address.country property on the person object.
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.
const person: Person = { address: { country: 'Chile', }, }; console.log(person.name?.first); // ๐๏ธ undefined
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.
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 an error occurred.
You might have used the logical AND (&&) operator to get around this in the past.
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 try to access the first property on the name object.
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.
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 specified value in the array.
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.
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 will just short-circuit returning
undefined instead of calling the function.
You can learn more about the related topics by checking out the following tutorials: