Some lesser known TypeScript notation
Tags: react, typescript, formik
Published: 2021-08-07 10:43:40

---
title: Some lesser known TypeScript notation
published: true
date: 2021-08-07 00:00:00 UTC
tags: react, typescript, formik
description: Exclamation mark notation and casting as unknown
canonical_url: https://bionicjulia.com/blog/lesser-known-typescript-notation
---

### Exclamation Mark / Bang operator

I recently came across the following notation in the codebase I was working on, and got very confused about what the exclamation mark / bang operator was for, after `userInfo`.

```jsx
const initialFormValues: LocationData = {
  currentCountry: props.route.params?.userData?.userInfo!.current_country_code ? 'x' : 'y',
};
```

I thought it was new Javascript notation at first, but subsequently found out that it's specifically for Typescript. Basically, in this case, `props.route.params?` may or may not be present, hence the presence of the `?`. It follows on that `userData` may therefore also not be present. However, if `userData` is present, `userInfo` will definitely be available, so it would not be correct to have `userData?.userInfo?`. If you just leave it as `props.route.params?.userData?.userInfo.current_country_code` however, the Typescript compiler will complain about `userInfo` potentially being undefined. So what to do?

Enter the bang operator. By adding `!` after `userInfo`, you're telling Typescript to stop complaining because you're explicitly saying that it cannot be `null` or `undefined` here. _Thanks for trying to guard us Typescript, but we know better in this case._ 😉

### Casting as "unknown"

The second Typescript notation that I recently learnt about was resetting types by casting as "unknown". What does this mean? Here's a concrete example:

Let's assume I have a Formik form. If you've not heard of Formik before, it's a very popular form library that's widely used in React and React Native apps (check out my other blog posts on Formik if you're interested). The nice thing about Formik is that it comes nicely typed and plays very nicely with a Typescript app. The other nice thing is that Formik works by effectively managing your form's state for you in such a way that you can easily abstract out your various form components and use Formik's context to access things like form values across different components.

So in the code example below, I have a `Formik` wrapper component, which has 3 different input fields and a submit button. I've abstracted out the 3 input fields into their own components, for `MechanismQuestion`, `DateQuestion` and `LocationQuestion`.

As I'll be running validation checks within each field component, I need to access the Formik state to see what the form values are, and therefore need to pass `formikProps` as a prop into each component (essentially passing down the current Formik form values that are in state into each component).

```jsx
export interface MechanismData {
  mechanism: string;
}

export interface DateData {
  date: Date;
}

export interface LocationData {
  location: string;
}

<Formik
  // ... add Formik config here
>
  {(props) => { // props is provided by Formik
    return (
      <Form>
        <MechanismQuestion
          formikProps={props as unknown as FormikProps<MechanismData>}
        />
        <DateQuestion formikProps={props as unknown as FormikProps<DateData>} />
        <LocationQuestion
          formikProps={props as unknown as FormikProps<LocationData>}
        />
        <Button>Submit</Button>
      </Form>
    )
  }}
</Formik>
```

The `formikProps` contains all of the form's current values i.e. the value of mechanism, date and location. However, if say we just considered `LocationQuestion`, this component really only cares about location and I therefore want to strictly type this component to only accept the form values that pertain to location.

Simple right? Let's just recast `props` to a new type!

Unfortunately not so simple - if I had done something like the below, Typescript would have complained because `props` already has its defined type from Formik (containing everything in Formik's state) and therefore thinks we've made a mistake in wanting to take on another custom type of `LocationData`.

```jsx
<LocationQuestion
  formikProps={props as FormikProps<LocationData>}
/>
```

What we therefore need to do in this case, is to recast `props` as `unknown`, before then recasting again into the specific type we want. What this does is to essentially erase the currently set type for `props`, so that we can happily define our new type for it.

```jsx
<LocationQuestion
  formikProps={props as unknown as FormikProps<LocationData>}
/>
```