Optional chaining in JavaScript and TypeScript

Piotr Pliszko

When accessing data located deep in object structure, we used to have to check if every parent object exists. Let's say we have this simple object which contains other objects:

const data = {
  someObject: {
    a: 1,
    b: 2,
    c: 3,
  },
  someOtherObject: {
    a: 1,
  },
};

If we would access existing property, everything works fine

❯ data.someObject.c
3

The same if we want to access non-existing property of existing object

❯ data.someObject.d
undefined

But what about a situation, when we try to access a property of an object that may, or may not exist?

❯ data.nonExistingObject.a
Uncaught TypeError: data.nonExistingObject is undefined

To handle this type of error, we would need to first check if object exists. It's ok if we have such a simple case like in the example. But what if we have a deep nested object? The condition we would need to use in if statement would be really long and not really readable.

And there optional chaining operator comes in handy.

Optional chaining operator

From MDN:

The optional chaining operator (?.) enables you to read the value of a property located deep within a chain of connected objects without having to check that each reference in the chain is valid.

Syntax:

obj.val?.prop;
obj.val?.[expr];
obj.arr?.[index];
obj.func?.(args);

So how can we fix our example? Just add ? after property that may be nullish

❯ data.nonExistingObject?.a
undefined

That way we don't get any errors, just an information that this values doesn't exist.

Other use cases

But can this operator be used also for use cases other than just simple object? Of course. We can use it also with arrays and functions.

Arrays

const data = {
  array: [1, 2, 3],
};
❯ data.array[0]
1
❯ data.nonExistingArray[0]
Uncaught TypeError: data.nonExistingArray is undefined
❯ data.nonExistingArray?.[0]
undefined

Functions

const data = {
  someFunction: (a) => a * 2,
};
❯ data.someFunction(2)
4
❯ data.nonExistingFunction(2)
Uncaught TypeError: data.nonExistingFunction is not a function
❯ data.nonExistingFunction?.(2)
undefined
If you have any questions or feedback, feel free to reach out to me on GitHub, X or LinkedIn!