Optional Chaining (?.), Nullish Coalescing (??), and Non-Null Assertion Operators (!) in TypeScript
Tags: typescript, javascript
Published: 2020-02-14 21:45:21

---
title: Optional Chaining (?.), Nullish Coalescing (??), and Non-Null Assertion Operators (!) in TypeScript
published: true
description: Have you seen TypeScript notation with ?., ?? or ! and wondered what these operators were? Learn about these operators and how to use them together for cleaner, less verbose code.
tags: typescript, javascript
---

If you've worked with JavaScript you've probably become all to familiar with the following error: `TypeError: Cannot read property 'value' of undefined` where value is a property on an object that you are trying to access. For example, if you are expecting to receive an object from an API, you might have something in your code like this:
```javascript
const cat = response.data.animals.cat;
```
But if the API didn't return any `animal` object, then this code would throw the error `TypeError: Cannot read property 'cat' of undefined`. It's even possible that your response object doesn't even have the data object, and you end up with an error like `TypeError: Cannot read property 'animals' of undefined`.

To avoid these errors, we usually write something like this:
```javascript
let cat;
if (response.data && response.data.animals) {
  cat = response.data.animals.cat;
}
```

But now, not only is this code more verbose, `cat` is no longer a constant (since using `const cat` within the if statement would make it unusable outside of the if statement).

You might also try using ternary operators to make your code a bit less verbose and keep the `const`, like this:
```javascript
const cat = response.data && response.data.animals ? response.data.animals.cat : undefined;
```

## Optional Chaining Operator

This is where optional chaining (the **Optional Chaining operator**) comes in for JavaScript (currently in stage 4 and has recently arrived in Chrome) and TypeScript (since version 3.7, November 6, 2019). Now we can achieve what the previous two snippets of code did with less verbosity:
```javascript
const cat = response.data?.animals?.cat;
```

In this case, `cat` will be undefined if `response.data` is undefined or if `response.data.animals` is undefined, instead of throwing an error. This looks a lot more like the first snippet of code we attempted to use.

To further understand how this works, here is what the [TC39 proposal](https://github.com/tc39/proposal-optional-chaining) states:
> If the operand at the left-hand side of the `?.` operator evaluates to undefined or null, the expression evaluates to undefined. Otherwise, the targeted property access, method or function call is triggered normally.

## Nullish Coalescing Operator

What if we don't want `cat` to be undefined if `response.data` or `response.data.animals` is undefined? Let's say we want `cat` to be a string, `"No cat could be found."`.

Normally, we might do something like this:
```javascript
let cat;
if (response.data && response.data.animals) {
  cat = response.data.animals.cat;
}
else {
  cat = "No cat could be found.";
}
```

Or, using the ternary operator:
```javascript
const cat = response.data && response.data.animals ? response.data.animals.cat : "No cat could be found.";
```

There is another operator, also in stage 4 for JavaScript and currently available in TypeScript, called the **Nullish coalescing operator** that can be used together with optional chaining to make our lives a little easier:
```javascript
const cat = response.data?.animals?.cat ?? "No cat could be found.";
```

If you are not used to this syntax it may take a little getting used to, but should help make your code less verbose.

Again, a snippet from the [TC39 proposal](https://github.com/tc39/proposal-nullish-coalescing) that may help understand how this operator works:
> If the expression as the left-hand side of the `??` operator evaluates to undefined or null, its right-hand side is returned.

This operator is also useful when working with falsy values that are not `null` or `undefined`. For example, the following will print `Hello` since the string is empty and therefore falsy, even if it is not `null` or `undefined`:
```javascript
const someEmptyValue = '';
console.log(someEmptyValue || 'Hello');
```

The same is true for the following, since `0` is also falsy:
```javascript
const someZeroValue = 0;
console.log(someZeroValue || 'Hello');
```

And for the following, since `false` is also falsy:
```javascript
const someFalseValue = false;
console.log(someFalseValue || 'Hello');
```

The results of these examples may be what we intend, depending on the application, but there are cases where we only want them to be falsy if they are `null` or `undefined` (called nullary values) and not the other cases.

For example, the following will print an empty string, 0, and false respectively, and not "Hello":
```javascript
const someEmptyValue = '';
console.log(someEmptyValue ?? 'Hello');

const someZeroValue = 0;
console.log(someZeroValue ?? 'Hello');

const someFalseValue = false;
console.log(someFalseValue ?? 'Hello');
```

This nullish coalescing operator can be super useful if you're not sure if an optional argument for a function is being passed and you want to use different logic depending on whether or not it is. Consider this TypeScript snippet:
```typescript
let inputValue: string = 'Jane Doe';
const validateInput = (value?: string | undefined) => {
  const checkValue: string = value ?? inputValue;
  if(!checkValue) {// will check for an empty string in this case
    return false;
  }
  return true;
}
```

With this snippet, we could pass a value to the function, for example `validateInput(someNewValue)` and the validation will occur on the value passed. However, if no value is passed as in `validateInput()` then the validation will occur on `inputValue` (this may be a state variable that is updated when the input is changed, for example).

## Non-Null Assertion Operator

There may be times when you are writing TypeScript that you put in checks to ensure that a variable is not going to be null or undefined later in the code, but the compiler throws an `Object is possibly 'null'` or `Object is possibly 'undefined'` error, or something like `undefined is not assignable to number`. For example:
```typescript
const addNumbers = (a: number | undefined, b: number) => {
  const c: number = a;// throws an error
  const d: number = b;
  return c + d;
}

```

Normally, this is a good thing, but imagine we had a scenario where we know that `a` and `b` are numbers whenever this function is called, even though they could be `undefined` at some other point in the program. Maybe you have some state in a React app that is initially undefined, but at the point that a function like this is called they are always already set. You can use the **non-null assertion operator** for these cases. This works if you have the `--strickNullChecks` flag turned on and are writing TypeScript (not JavaScript).
```typescript
const addNumbers = (a: number | undefined, b: number) => {
  const c: number = a!;// no error
  const d: number = b;
  return c + d;
}

```

Be careful when using this operator though! If `a` turns out to be undefined anyway, no error will be thrown for `c` and `c` will end up `undefined` even though it should not have that type. Essentially, the code will fall back to JavaScript instead of using the type checks that TypeScript provides. This is a type annotation that does not change the compiled code. It is usually better to use null checks when you can (like using the previous two operators). You can read more about this operator in this article: [Cleaner TypeScript With the Non-Null Assertion Operator](https://medium.com/better-programming/cleaner-typescript-with-the-non-null-assertion-operator-300789388376).

## Conclusion

I hope this article is useful for anyone learning TypeScript who hasn't learned about these operators yet. Feel free to leave a comment if you need clarification or if you find a typo or inaccuracy. 💕