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:
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.
const foo = a && a.b && a.b.c && a.b.c.d && a.b.c.d[0];
A lodash solution might look like
const foo = _.has(a, 'b.c.d[0]');
The safe navigation operator approach looks like
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.
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.
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.
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.
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.
!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
.
!!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!
Top comments (4)
The safe navigation operator also pairs well with the nullish coalescing operator for providing defaults like what you get with lodash get:
const foo = get(a, 'b', {});
can be expressed as
const foo = a?.b ?? {};
And the nullish coalescing operator protects from logical bugs where you want 0 or false to be considered valid values.
Bang! Bang! Bang! - sounds pretty unsafe to me
Bang! as a postfix operator in typescript is unsafe I agree. But JavaScript Bangs aren't unsafe . They are used just to convert any value to a Boolean equivalent.
No sorry, it was a joke - bang! bang! bang! sounds like a triple gunshot which is obviously unsafe.