Wednesday, July 6, 2022
HomeWeb DevelopmentUnderstanding the exclamation mark in TypeScript

Understanding the exclamation mark in TypeScript


The exclamation mark ! is named the non-null assertion operator in TypeScript. We will probably be utilizing these phrases interchangeably on this article. However what does this operator do?

On this article, we’ll check out:

What’s the TypeScript exclamation mark?

The non-null assertion operator tells the TypeScript compiler {that a} worth typed as optionally available can’t be null or undefined. For instance, if we outline a variable as probably a string or undefined, the ! operator tells the compiler to disregard the opportunity of it being undefined.

What the exclamation mark does in TypeScript

Let’s say a variable is outlined as probably null or undefined, like so:

let x: string | undefined 

Or, let’s say a perform is outlined to just accept an optionally available argument, like so:

perform printString (str ?: string) { … }

In these circumstances, if we attempt to reference that variable as a particular sort, then the TypeScript compiler would give us an error message, similar to the next:

Object is probably 'undefined'. ts(2532)

We are able to use the non-null assertion operator to inform the compiler explicitly that this variable has a price and isn’t null or undefined. Let’s assessment a number of examples to raised perceive the exclamation mark in TypeScript.

Instance 1: Utilizing a variable of sort string | null for a perform that accepts string

Let’s say we outlined a variable phrase with the sort as string | null. This implies all through our code, phrase can both maintain a string worth or a null worth.

If we try to make use of a perform solely out there to string varieties on phrase, TypeScript will reject it as a result of there’s a risk in our code that phrase holds a null worth sort:

let phrase : string | null = null
const num = 1
if (num) {
    phrase = "Hi there World!"    
}
console.log(phrase.toLowerCase()) // Error: Object is probably 'null'.ts(2531)

Utilizing the ! non-null assertion operator, we will inform TypeScript we’re sure phrase won’t ever be null (or undefined), so it may possibly confidently apply string capabilities to it:

let phrase : string | null = null
const num = 1
if (num) {
    phrase = "Hi there World!"    
}
console.log(phrase!.toLowerCase())

With this small addition, the compiler not believes there’s a risk that phrase is null.

Instance 2: Assigning the worth of an optionally available argument to a variable inside a perform

In one other instance, let’s say we created a perform printName that accepts an optionally available argument personName.

Be aware that defining a perform argument as optionally available utilizing ?: is identical as defining sort as probably undefined. For instance, arg?: string is identical as arg: string | undefined.

If we attempt to reassign that optionally available argument personName to a different variable of sort string, the next would happen:

perform printName(personName?: string) {
    const fullName: string = personName 
/** 
 * Error: Sort 'string | undefined' will not be assignable to sort 'string'. 
 * Sort 'undefined' will not be assignable to sort 'string'.
 */
    console.log(`The identify is ${fullName}`)
}

We are able to repair the TypeScript errors thrown in our snippet above utilizing the ! operator:

perform printName(personName?: string) {
    const fullName: string = personName! 
    console.log(`The identify is ${fullName}`)
}

Now, the compiler understands that personName can’t be null or undefined, making it assignable to sort string.

Instance 3: Printing the attribute of an optionally available object argument inside a perform

In our closing instance, we’ll outline a kind Individual and a perform printName that accepts an optionally available argument of sort Individual. Let’s see what occurs if we attempt to use printName to print the identify attribute of Individual:

interface Individual {
    identify: string
    age: quantity
}

perform printName(individual?: Individual) {
    console.log(`The identify is ${individual.identify}`) // Error: Object is probably 'undefined'. ts(2532)
}

Let’s repair this TypeScript error utilizing our ! operator:

interface Individual {
    identify: string
    age: quantity
}

perform printName(individual?: Individual) {
    console.log(`The identify is ${individual!.identify}`)
}

Be aware that TypeScript has an alternate for referencing attributes and capabilities on objects that is perhaps null or undefined known as the optionally available chaining operator ?. . For instance, individual?.identify or phrase?.toString() will return undefined if the variable will not be outlined or null.

Nonetheless, the optionally available chaining operator ?. can not resolve the TypeScript errors in our second instance, by which we tried to assign the worth of a variable sort string | undefined to a variable sort string. Be taught extra about optionally available chaining within the final part of this text.

As we’ve seen in our examples, the ! operator could be very helpful when we wish TypeScript to deal with our variable as a strong sort. This prevents us from having to deal with any null or undefined circumstances after we are sure there isn’t a such case.

Now that now we have seen some examples to achieve a greater understanding of the TypeScript exclamation mark, let’s take a look at some widespread use circumstances for this operator.

Performing lookups on an array

Let’s think about now we have an array of objects and we need to choose an object with a selected attribute worth, like so:

interface Individual {
    identify: string
    age: quantity
    intercourse: string
}

const individuals: Individual[] = [
  {
      name: 'Gran',
      age: 70,
      sex: 'female'
  },
  {
      name: 'Papa',
      age: 72,
      sex: 'male'
  },
  {
      name: 'Mom',
      age: 35,
      sex: 'female'
  },
  {
      name: 'Dad',
      age: 38,
      sex: 'male'
  }
]

const femalePerson = individuals.discover(p => p.intercourse === 'feminine')

In our snippet above, TypeScript will outline the kind of femalePerson as Individual | undefined as a result of it’s attainable that individuals.discover yields no outcome — in different phrases, that it will likely be undefined.

Nonetheless, if femalePerson has the sort Individual | undefined, we won’t be able to go it as an argument to a perform anticipating sort Individual.

After we are performing lookups on these arrays, we are sometimes assured that they’ve outlined values, and we subsequently don’t consider any undefined circumstances exist. Our ! operator can save us from extra — or pointless — null or undefined case dealing with.

Add the non-null assertion operator, like so:

const femalePerson = individuals.discover(p => p.intercourse === 'feminine')!

This is able to make femalePerson have the sort Individual.

React refs and occasion dealing with

React refs are used to entry rendered HTML DOM nodes or React parts. Refs are created utilizing React.createRef<HTMLDivElement>() after which hooked up to the factor utilizing the ref attribute.

To make use of React refs, we entry the present attribute, ref.present. Till the factor is rendered, ref.present may very well be null, so it has the next sort:

HTMLDivElement | null

To connect an occasion to ref.present, we’d first must deal with attainable null values. Right here is an instance:

import React from 'react'

const ToggleDisplay = () => {
    const displayRef = React.createRef<HTMLDivElement>()

    const toggleDisplay = () => {
        if (displayRef.present) {
            displayRef.present.toggleAttribute('hidden')
        }
    }

    return (
        <div>
            <div class="display-panel" ref="displayRef">
                <p> some content material </p>
            </div>
            <button onClick={toggleDisplay}>Toggle Content material</button>
        <div>
    )
}

Within the snippet above, we needed to deal with a kind test of displayRef.present utilizing an if assertion earlier than calling the toggleAttribute perform.

Generally, we’re certain that if the button onClick occasion is triggered, then our parts are already rendered. Subsequently, there isn’t a want for a test. This pointless test may be eradicated utilizing the ! operator, like so:

const displayRef = React.createRef<HTMLDivElement>()

const toggleDisplay = () => displayRef.present!.toggleAttribute('hidden')

return (
        <div>
        ...

The draw back of utilizing the exclamation mark in TypeScript

The ! operator doesn’t change the runtime conduct of your code. If the worth you’ve got asserted will not be null or undefined seems to really be null or undefined, an error will happen and disrupt the execution of your code.

Bear in mind, the distinction between TypeScript and JavaScript is the assertion of varieties. In JavaScript we don’t want or use the ! operator as a result of there isn’t a sort strictness.

A JavaScript variable may be instantiated with string and adjusted to object, null, or quantity in the course of the execution of the code. This leaves it as much as the developer to deal with the totally different circumstances.

Utilizing the ! operator takes away TypeScript’s “superpower” of stopping runtime sort errors. Subsequently, it’s not one of the best apply to make use of the ! operator.

Options to utilizing the TypeScript exclamation mark

You could possibly use optionally available chaining or sort predicates as alternate options to non-null assertions.

Optionally available chaining is a TypeScript shorthand that permits us simply deal with the circumstances the place the variable is outlined or not. When the variable will not be outlined or null, the referenced worth defaults to worth undefined. Right here’s an instance of optionally available chaining:

interface Individual {
    identify: string
    age: quantity
    intercourse: string
}

perform printName(individual?: Individual): void {
    console.log('The identify of this individual is', individual?.identify)
}

In our instance above, if individual is undefined, our print output can be as follows:

'The identify of this individual is undefined'

Utilizing sort predicates in TypeScript is completed by defining a perform that performs a boolean take a look at and returns a kind predicate within the kind arg is Sort. Right here is an instance:

interface Individual {
    identify: string
    age: quantity
    intercourse: string
}

perform validatePerson(individual?: Individual) individual is Individual {
    return !!individual
}

Utilizing this kind predicate, we will first validate the thing earlier than performing any additional operations, like so:

perform printName(individual?: Individual) {
    if (!validatePerson(individual)) {
        console.log('Individual is invalid')
        return
    }

    console.log(`The identify is ${individual.identify}`)
}

Conclusion

TypeScript’s energy over JavaScript is the sort security it gives our code. Nonetheless, we might generally need to disable TypeScript’s strict sort checks — for instance, for the sake of flexibility or backward compatibility. In such circumstances, we will use the non-null assertion operator.

Although a helpful function, I encourage you to discover safer sort assertion strategies as an alternative. You may go a step additional to stop use of this operation in your mission and along with your crew by including the typescript-eslint package deal to your mission and making use of the no-non-null-assertion lint rule.

Writing a whole lot of TypeScript? Watch the recording of our current TypeScript meetup to find out about writing extra readable code.

TypeScript brings sort security to JavaScript. There is usually a stress between sort security and readable code. Watch the recording for a deep dive on some new options of TypeScript 4.4.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments