Use of the Exclamation Mark in TypeScript
Tags: development, essentialjs2, typescript, web
Published: 2022-12-12 04:20:02

---
title: Use of the Exclamation Mark in TypeScript
published: true
date: 2022-12-06 11:00:42 UTC
tags: development, essentialJS2, typeScript, web
canonical_url: https://www.syncfusion.com/blogs/post/exclamation-mark-in-typescript.aspx
cover_image:  https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ml4mpuhsux7hk9ey83j8.png
---
## The exclamation mark in TypeScript

In many scripting languages, developers use the exclamation mark as a **not** operator. But when working with TypeScript, the exclamation mark acts as a non-null assertion operator. This non-null assertion will remove null and undefined values.

In this article, I will discuss several uses of the exclamation mark in TypeScript.

## How does the exclamation mark behave in TypeScript?

Let’s see some simple examples of how the exclamation mark is used in TypeScript.

### When defining a variable

If we define a string-type variable as **string | null** , it means that the variable holds a string or null value. But suppose we define a function that accepts only a string type as a parameter. In that case, the TypeScript compiler will reject our variable value since there is a possibility that it will have a null value. Refer to the following code:

```js
let stringWord: string | null

const number =1
if(number){
  stringWord = “Test word”
}
console.log(stringWord.toUpperCase())

```

In this case, the following error will appear:

```bash
Error: Object is possibly ‘null’.ts(2531)
```

However, if you use the non-null assertion operator, you can convey to the TypeScript compiler that the **stringWord** variable is never null or undefined.

This is what the modified code looks like:

```js
let stringWord: string | null

const number =1
if(number){
  stringWord = “Test word”
}
console.log(stringWord!.toUpperCase()) // added the exclamation mark
```
### When passing a value as an optional argument in a function

Consider a function we use to get a student’s details. The function will accept the parameter **studentName.**

```js
Function getDetails(studentName ?: string){
  const name: string = studentName
  const age: number = 25
  console.log(“Name : ${name}”)
  console.log(“Age: ${age}”)
}
```

In the above code example, you can see the use of **?** after the parameter. In TypeScript, the question mark is used to define an argument as optional. It is the same as specifying the type as undefined. It is similar to **studentName: string | undefined**.

The above function will throw the following error.

```bash
Error: Type ‘string | undefined’ is not assignable to type ‘string’. 
Type ‘undefined’ is not assignable to type ‘string’.
```

The reason for this error is that the compiler considers **studentName** as a null value or undefined value. We can solve this issue by adding an exclamation mark after the **studentName** and making it a string type.

```js
Function getDetails(studentName ?: string){
  const name: string = studentName!
  const age: number = 25
  console.log(“Name : ${name}”)
  console.log(“Age: ${age}”)
}
```

### When getting the attribute of an optional object within a function

Here, we define a type **Student** and the function **getName** that accepts an argument of type **Student.**

```js
type Student ={
  sid : number;
  name: string;
};
  
function getName(std ?: Student){
  console.log("Name of the student is ${std.name}")
}
```

In this function, the **std** parameter is marked as an optional parameter, so we cannot safely access the property of **std.** It can be either a Student type or an undefined type. If we don’t use the non-null assertion operator, we will get the following error:

```bash
Error: Object is possibly 'undefined'. ts(2532)
```

To avoid this error, inform the compiler that this variable will never be undefined or null. Introducing the non-null assertion to this code will solve this error.

```js
type Student ={
  sid : number;
  name: string;
};
  
function getName(std ?: Student){
  console.log("Name of the Student is ${std!.name}");
}
```
## Use cases for the exclamation mark as a non-null assertion operator

Let’s discuss some use cases for the exclamation mark as a non-null assertion in TypeScript.

### Search for an item that exists in a list

Let’s consider a scenario where specific items exist in a list and you need to access those elements and check them.

```js
interface Student {
     sid : number;
     name: string;
};

const students: Student[] =[
   {
      sid : 1,
      name: "Alex",
   },
   {
      sid : 2,
      name: "Gerome",
   },
   {
      sid : 3,
      name: "Bennet",
   },
 ];

 const getStudent =( sid: number) => {
      return students.find((students) => students.sid ==sid);
 };

 const students = getStudent(1);

```

In the above code example, we have a list of students, and we need to find the student details based on the student **ID, sid.** Everything looks fine in the code but imagine if the type of the variable **students** can be undefined. In this case, we cannot pass **sid** as an argument.

Most of the time, we feel confident that these arrays have only defined values when we perform a search on them. In practice, though, we should prepare the application for handling null or undefined cases too. This can be easily achieved using the **!** operator.

The following code snippet shows how to address this case using the non-null assertion operator.

```js
const getStudent =( sid: number) => {
   return students.find((students) => students.sid ==sid)!;
   //Add the exclamation mark
};

const students = getStudent(1);
```

### Handling React refs in TypeScript

React refs provide a way to access DOM nodes or React elements. When we use React refs, we have to access the current attribute, **ref.current**.

This attribute is in a null state until the rendering happens, or it can take the following type:

```js
HTMLDivElement | null
```

Let’s explore the way to handle this null using an example.

```js
// some code
    
const App = () => {
    const ref = useRef(null);
  
    const handleClick = () => {
      if(ref.current) {
        console.log(ref.current.getBoundingClientRect());
      }
    };
  
    return (
      <div className="App" ref={ref}>
        {/* ... */}
        <button onClick={handleClick}>OK</button>
      </div>
    ); 
};
```

Here, we created a component with access to the **div** element with the **App** class DOM node. Clicking on the **Ok** button will display the size of the component and its position in the viewport.

There are times when the UI element will not be rendered when a click action is performed on the OK button. This might lead to an exception during runtime. The **!**  operator can be used to eliminate this pointless check. Refer to the following code example:

```js
const handleClick = () => {
  if(ref.current) {
     console.log(ref.current!.getBoundingClientRect());
  }
};
```
## When is the exclamation mark assertion not useful?

Even though we added the **!** operator to handle null and undefined issues; this operator does not change any runtime behavior of your code. Errors can still disrupt the execution even if you handle the null and undefined issues with the non-null assertion operator.

Unlike JavaScript, TypeScript uses assertions for types. JavaScript variables can handle type issues during execution time. So, handling type issues depends on the scenario developers face when dealing with such problems.

The **!** operator is TypeScript’s main advantage for preventing runtime errors. Therefore, we need to focus more on adding additional checks to handle non-null issues since the **!**  operator is not the best practice for handling such matters.

## Alternatives to the exclamation mark operator in TypeScript

You can use a few other options you can use as an alternative to the **!** operator in TypeScript.

### Type predicates

In TypeScript, type predicates define a function and perform a Boolean test which returns a type predicate. It will handle the null and undefined issues beforehand.

```js
interface Student {
  sid : number;
  name: string;
};
 
function validateStudent(std?: Student) std is Student{
 return !! std
}
```

We have to add the type predicate as shown in the above code sample. After that, we can perform the validation before the core functions in our code.

```js
function getName(std ?: Student){
  if (!validateStudent(std)) {

     console.log('Student is invalid');
     return
  }
  console.log("Name of the Student is ${std.name}");
}
```

### Optional chaining

Optional chaining changes the reference value defaults to **undefined** even if the variable is undefined or null. Let’s see the following example:

```js
interface Student {
  sid : number;
  name: string;
};

function getName(std ?: Student): void {
  console.log("Name of the Student is ", std?.name);
}
```

If the **std** is **undefined,** it will display the following output:

```js
Name of the Student is undefined
```
## Conclusion

TypeScript’s superpower is its type safety. However, in some cases, we have to disable the strict type checks. If you want to add more flexible code components to your code, you can use the non-null assertion-type operations covered in this blog.

Even though **!** is a helpful operator, developers must be careful when using it, or they may get stuck with unknown runtime errors. But if you like your code less lengthy and with fewer validations, you are welcome to use the exclamation mark operator.

Thank you for reading!

Syncfusion’s [Essential JS 2](https://www.syncfusion.com/javascript-ui-controls "Syncfusion Essential JS 2 UI controls") is the only suite you will need to build an app. It contains over 65 high-performance, lightweight, modular, and responsive UI components in a single package. Download a [free trial](https://www.syncfusion.com/downloads/essential-js2 "Syncfusion Essential Studio for JavaScript Free Trial") to evaluate the controls today.

If you have questions or comments, contact us through our [support forums](https://www.syncfusion.com/forums "Syncfusion Support Forums"), [support portal](https://support.syncfusion.com/ "Syncfusion Support Portal"), or [feedback portal](https://www.syncfusion.com/feedback/ "Syncfusion Feedback Portal"). We are always happy to assist you!

## Related blogs

- [JavaScript API Mocking Techniques](https://www.syncfusion.com/blogs/post/javascript-api-mocking-techniques.aspx "Blog: JavaScript API Mocking Techniques")
- [Understanding Conditional Types in TypeScript](https://www.syncfusion.com/blogs/post/understanding-conditional-types-in-typescript.aspx "Blog: Understanding Conditional Types in TypeScript")
- [Top 15 VS Code Extensions Every Developer Should Know](https://www.syncfusion.com/blogs/post/top-15-vs-code-extensions-every-developer-should-know.aspx "Blog: Top 15 VS Code Extensions Every Developer Should Know")
- [JavaScript String Manipulation Techniques Every Developer Should Know](https://www.syncfusion.com/blogs/post/javascript-string-manipulation-techniques-every-developer-should-know.aspx "Blog: JavaScript String Manipulation Techniques Every Developer Should Know")