Why should I start using Optional Chaining and Nullish Coalescing operators?

Gone are the days there you had to add incremental nullish (undefined or null) checks when fetching values in nested objects. Lets do more with less code.

These operator additions to the ECMAScript and JavaScript syntax removes the need for many of the conditional statements protecting against errors like; cannot read property of undefined.

Note: If you only need to configure ESLint to allow these syntaxes, jump to the configuration part.

Optional Chaining operator (?.)

Suppose that you have a person and you want to access the street of that persons address.

const street = person.address.street;

Now suppose that your data lacks the address for this particular person. Probably all JavaScript developers have forgotten add extra checks for these kind of cases from time to time.

The result for this would be that a familiar error will be thrown:

Uncaught TypeError: Cannot read property 'street' of undefined

Previously you needed to guard these cases if statements containing a lot of and operators.

For not so deeply nested structures:

const street = person.address && person.address.street;

// or for several properties maybe
const {address = {}} = person;
const street = address.street;
const number = address.number;

But for more deeply nested structures like const street = person.mother.address.street the problem becomes even worse.

This is where the optional chaining operator comes to the rescue.

const street = person.mother?.address?.street;
const streetNumber = person.mother?.address?.streetNumber;

If any of the objects in the tree on the right-hand side where to miss the next property the result will be undefined. No more checks and TypeError thrown.

Optional Chaining for function calls

The optional chaining can also be used to make conditional function calls only for existing functions.

const serializedPerson = person.toYAMLString?.()

This syntax might look a bit odd, it did to me too, but this was the way the language proposal ended up. They had problems with syntax with a single ? because of the difficulty for the parser to efficiently distinguish those forms from the conditional operator and none of the other proposals gained consensus.

Nullish Coalescing operator (??)

Especially when working with numbers it's easy to make the mistake of mixing up 0 and undefined in conditional statements. you might end up with code like:

value = (value === undefined || value === null) ? undefined : value;

The nullish coalescing operator lets you write this is in the shorter form:

value = value ?? undefined;

One use case for this is like above when cleaning out null values, another in template literals to make sure that empty variables will serialize to empty strings value ?? ''.

The operator will return undefined if the value is nullish, and otherwise the value.

Putting it all together

Lets put it all together in a template literal where we print inconsistent data about a few persons:

const jenny = {
  name: 'Jenny',
  phone: '123 45 67',
};

const henry = {
  name: 'Henry',
  address: {
    street: 'Leafstreet'
  },
  mother: jenny
};

const anna = {
  name: 'Anna',
  address: {
    street: 'Svartbäcksgatan',
    streetNumber: 32
  },
  father: henry
};

const people = [jenny, henry, anna];

const personTemplate = (person) => `
Name: ${person.name ?? ''}
Address: ${person?.address?.street ?? ''} ${person?.address?.streetNumber ?? ''}
Phone: ${person.phone ?? ''}
Father: ${person?.father?.name ?? ''}
Mother: ${person?.mother?.name ?? ''}
`.replace(/\s+(?=\n)/g, '');

console.log(people.map(personTemplate).join(''));

Will give the output:

Name: Jenny
Address:
Phone: 123 45 67
Father:
Mother:

Name: Henry
Address: Leafstreet
Phone:
Father:
Mother: Jenny

Name: Anna
Address: Svartbäcksgatan 32
Phone:
Father: Henry
Mother:

As we can see these two operators becomes really powerful when combined and makes for really compact code which I think is especially useful when working with template related tasks where you are often fine with just printing empty strings where values might be missing.

Configure ESLint for optional chaining and nullish coalescing operator

ESLint actually have built-in support for both operators in recent versions (optional chaining >= 7.5.0 and nullish coalescing operator => 7.2.0).

To have the syntax working with ESLint you must set ecmaVersion => 2020. As the time of writing their latest version is 2021 so you might go with that, just make sure to also grab the latest version the eslint npm package.

.eslintrc.json:

{
    "parserOptions": {
        "ecmaVersion": 2021
    }
}

This is all, lets clean up in the conditional guards and make our code more easy to read!