DEV Community

Cover image for Typescript: Bang operator considered harmful
Thomas Maximini
Thomas Maximini

Posted on

Typescript: Bang operator considered harmful

We recently ran into a few runtime errors in our frontend. People would get errors like Cannot read property x of null or Cannot read property .length of undefined and so on. Something propably every Javascript developer has encountered before.

Runtime error

no bueno!

But our codebase is a Next.js application written in Typescript. How did the Typescript compiler not catch those errors during compile time.

Digging a bit deeper, I found that we had a rule in our .eslintrc that turned off any warnings around using the bang(!) operator in Typescript:

// .eslintrc
rules: {
// ...
'@typescript-eslint/no-non-null-assertion': 'off'
}
Enter fullscreen mode Exit fullscreen mode

The Typescript docs define this as the non-null-assertion operator. The docs state

A new ! post-fix expression operator may be used to assert that its operand is non-null and non-undefined in contexts where the type checker is unable to conclude that fact. Specifically, the operation x! produces a value of the type of x with null and undefined excluded. Similar to type assertions of the forms x and x as T, the ! non-null assertion operator is simply removed in the emitted JavaScript code.

Sounds difficult. But all it does is basically telling the compiler "this value can not be null or undefined".

One of the great advantages of Typescript is that it checks your code instantly for any type errors (duh), so whenever you are working with an object or variable value that might be undefined, it gives you a warning.

Eslint showing a waarning

It usually does so by underlining the variable and showing you a little warning. The lazy developer might just go ahead, yell at Typescript that they know what they're doing and add a ! to it. Problem solved right?

This might cause the compiler to shut up, but then lead to the undesired runtime errors we saw above. It might be defined 99% of the time or even 100% of the time on your local machine. Especially when working with asynchronous code, such as GraphQL queries and mutations, it's important to know that objects and values can often be undefined. Maybe the data is still being loaded or something takes a while until it is initialized.

The problem is that these exclamation marks are difficult to miss in a code review. Maybe someone started using them, they end up in the codebase. The next pages are partly copied and pasted or newer developers see this and start copying the pattern. Suddenly you have exclamation marks all over your codebase because it seems to make Typescript happy.

A better alternative would be using the optional chaining ? operator that got introduced in Typescript 3.7.

And for React components, you can use the logical AND && operator:

// wrong
<VideoPresentation videoPresentation={videoPresentation!} />
// better
{videoPresentation && <VideoPresentation videoPresentation={videoPresentation} />}
Enter fullscreen mode Exit fullscreen mode

By setting the eslint rule correctly to '@typescript-eslint/no-non-null-assertion': 'error' we've now disallowed any usage of that operator. In my opinion it defeats the purpose of Typescript, which brings a lot of sanity and safety into bigger Javascript projects.

Do you agree or do you think there are valid use cases for the ! operator in Typescript. Let me know at Twitter.

Photo by Cindy Tang on Unsplash.

This post was originally published on My personal blog.

Top comments (4)

Collapse
 
kapcash profile image
Florent Catiau-Tristant

It may be useful in some edge cases imo. For instance in this dummy example:

   product: Product | null = null;

   init() {
      if (!this.product) {
         this.product = { title: 'my product' }
      }
      this.updateTitle();
   }

   updateTitle() {
      this.title = this.product!.title;
   }
Enter fullscreen mode Exit fullscreen mode

In the updateTitle method, you may not want to do the nullish check again and you know, from the context, that this.product cannot be null.
Here is the place to use the ! operator.

But in most cases, including this one (ones might add a non safe call to updateTitle), it's dangerous, I'll agree with that :)

Collapse
 
niieani profile image
Bazyli Brzóska

It's useful in unit tests. You don't want a line of code in a unit test to be skipped silently by using ?, you want it to throw, when something you expect to be non-nullable is actually null.
In some cases it might also be useful to workaround TS inadequacies - when TS inference is not good enough, and you've manually asserted that a property exists in the previous line.

Collapse
 
havespacesuit profile image
Eric Sundquist

Yup. ?. is your friend. !. is not.

Collapse
 
bc profile image
Brian Canzanella

Good find! Thanks for sharing this.