Beginner's TypeScript #9
Tags: programming, beginners, typescript
Published: 2023-12-26 15:00:00

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1sf03aadx6ohz1rt1rtw.png)

⭐ **Typing Promises and Async Requests** ⭐

We have a function called **fetchLukeSkywalker**:

```ts
export const fetchLukeSkywalker = async (): LukeSkywalker => {
  const data = await fetch("<https://swapi.dev/api/people/1>").then((res) => {
    return res.json();
  });

  return data;
}
```

It goes to the Star Wars API at swapi.dev and fetches **people/1**, corresponding to Luke Skywalker.

There is a **LukeSkywalker** type that includes properties based on what the API includes in the response:

```ts
interface LukeSkywalker {
  name: string;
  height: string;
  mass: string;
  hair_color: string;
  skin_color: string;
  eye_color: string;
  birth_year: string;
  gender: string;
}
```

However, TypeScript is showing us an error on the return type:

```bash
Type 'LukeSkywalker' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.
```

We will figure out how to update the return type annotations to make TypeScript happy.

👉 **Solution:**

➖ **Do What TypeScript Suggests:**

In the starting point of the code, hovering over the error message in VS Code pops up a message:

```bash
The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<LukeSkywalker>'?
```

We get this error because the **fetchLukeSkywalker** function is async, so the type returned will be a Promise.

Following TypeScript's suggestion to write **Promise<LukeSkywalker>** will fix this error:

```ts
export const fetchLukeSkywalker = async (): Promise<LukeSkywalker> => {
```

Note that this syntax is similar to the **Array<Post>** syntax we saw earlier. But unlike arrays, there's only one way to use **Promise<T>**.

This solution works well, and is probably what I would recommend.

➖ **Type the Fetched Data Response:**

The **data** returned from a fetch request will be typed as **any** by default.

Even though we know from the API what our response will contain, TypeScript has no idea. That means the **any** type does not give us any autocomplete when we use it.

```ts
export const fetchLukeSkywalker = async () => {
  // `data` will be typed as `any`
  const data = await fetch(
```

But because we have awaited the fetch, we can type data as **LukeSkywalker**:

```ts
const data: LukeSkywalker = await fetch(
```

This would give us the autocomplete because it's been properly typed.

Now, when we hover over the **fetchLukeSkywalker** function declaration, we can see that TypeScript has inferred the return type of the function to be **Promise<LukeSkywalker>** just like we saw in the prior solution.

➖ **Cast Data as a Type:**

In the cases we have looked at so far, we are kind of lying to ourselves a little bit.

TypeScript does not know what we are going to return, so we have to tell it. But really, we do not know what the result of our fetch is going to be.

This is where this solution comes in:

```ts
export const fetchLukeSkywalker = async () => {
  const data = await fetch("<https://swapi.dev/api/people/1>").then((res) => {
    return res.json();
  });

  // cast the data to LukeSkywalker
  return data as LukeSkywalker;
}
```

The ** return data as LukeSkywalker** line casts the fetch response to our **LukeSkywalker** type.

When working with fetch requests, we should either cast the return data as a type or assign a type to the data when the request is made.

✍️ **More About Casting:**

Casting allows us to let anyone become **LukeSkywalker**:

```ts
const uri = {} as LukeSkywalker
```

Compare the above to if we said **uri** was assignable to **LukeSkywalker**:

This would give us errors because the object does not include the appropriate properties.

Generally speaking, the assigning syntax is safer than the **as** syntax and is probably what you should do in most cases.

---

I hope you found it useful. Thanks for reading. 🙏

Let's get connected! You can find me on:

- **Medium:** https://medium.com/@nhannguyendevjs/
- **Dev**: https://dev.to/nhannguyendevjs/
- **Hashnode**: [https://nhannguyen.hashnode.dev](https://nhannguyen.hashnode.dev/)/
- **Linkedin:** https://www.linkedin.com/in/nhannguyendevjs/
- **X (formerly Twitter)**: https://twitter.com/nhannguyendevjs/