Safe Navigation Operator? Bang! Bang Bang!!
Tags: javascript, typescript
Published: 2021-03-12 18:51:31

# Safe Navigation Operator

Safe navigation operator or optional chaining is now available in JavaScript and TypeScript >= v3.7🎉.

It provides easy access to deeply nested values, so checking for `nullish` (`undefined` or `null`) values is simplified. We avoid hitting the classic JavaScript error:
```css
Uncaught TypeError: Cannot read property 'foo' of undefined.
```
A common workaround would be to short-circuit using the `&&` operator. However, this would quickly unwind to long repetitive chains if we need to check for a deeply nested object.
```javascript
const foo = a && a.b && a.b.c && a.b.c.d && a.b.c.d[0];
```
A lodash solution might look like 
```javascript
const foo = _.has(a, 'b.c.d[0]');
```
The safe navigation operator approach looks like
```javascript
const foo = a?.b?.c?.d[0];
```
Returns `undefined` if the value does not exist.

This approach is recommended since it has now been added to the language and is browser supported. //! Except Internet Explorer

This also works with function calls, array indexes and chaining dynamic expressions.
```javascript
const foo = a?.b //accessing object property
const foo = a?.[expr] //accessing through dynamic expression
const foo = arr?.[index] //accessing array index
const foo = bar?.(args) //conditional function call
```
Warning: This operator is not valid on the left-hand-side of an assignment operator.
```css
const a?.b = foo; //Invalid
```
Note: `?.` acts differently than `&&` operator, since the `&&` operator acts on `falsy` values(including `0`, `NaN`, `""`, `false`), but `?.` acts on `nullish` values (`null` and `undefined`).


# TypeScript Bang! (non-null assertion operator)

Warning: `!.` is not the same as `?.` . The `!` postfix expression is valid in TypeScript >= v2.0. The `a!` operator produces a value `a` with `null` and `undefined` excluded. Meaning, this will explicitly tell the compiler that you are sure the type of value is not `null` or `undefined`. The compiler will thus not check if the value is `null` or `undefined` in compile time.

This could come in handy while working with maps.
```typescript
const value = map.has('key') && map.get('key')!;
```
In this case, the compiler does not keep track that map.has() has been evaluated while evaluating map.get(). So the compiler can't determine if the map returns a safe value. 

This can also be used in terms of calling a possibly undefined function and array indexes.
```typescript
func!(args);
arr![0];
```

For example it could be used when using React refs. When using refs, the current value may be null if the element is unmounted.


# JavaScript Bang! (prefix operator)

In JavaScript every value is assocaiated as either a `truthy` value or a `falsy` value. So, a bang(`!`) as a prefix on a value acts as a logical "not" operator on that value.

```javascript
!true; //returns false
!false; //returns true

!1 //returns false
!5 //returns false

!0 //returns true
!NaN //returns true
!null //returns true
!undefined //returns true

![] //returns false (points to a reference)

const foo = "bar";
!foo //returns false

const baz = null;
!baz //returns true
``` 


# JavaScript Bang Bang!!

Since a bang (`!`) acts as a logical "not" on a value, a double bang negates the result of the logical "not" operation. So, a double bang will first change the value to a boolean opposite, and return the opposite of that. In other words, it converts any value into a boolean type. 

Note: The `!` operator operates on `truthy` and `falsy` values and is not limited to `nullish` values. So, `!''` should resolve to `true`.

```javascript
!!true //returns true
!!false //returns false

!!null //returns false
!!undefined //returns false
!!NaN //returns false

!!34 //returns true
!!0 //returns false

!!'foo' //returns true
!!'' //returns false

!!['foo'] //returns true
!![] //returns true (points to a reference)

!!{foo: 'bar'} //returns true
!!{} //returns true (points to a reference)
```


Happy Hacking!