Typesafe HTTP Request in Node
Tags: typesafe, node, fetch
Published: 2024-06-28 13:07:18

Ensuring that HTTP requests and responses are typesafe is crucial in modern web development. It prevents errors, improves code readability, and enhances developer productivity. This article explores how to implement typesafe HTTP requests in a Node.js environment using TypeScript and Fetch.

## Why Typesafe HTTP Requests?
Type safety in HTTP requests means defining and enforcing the structure of request payloads and response data. This practice provides several benefits:

Error Prevention: Catch type mismatches at compile-time rather than runtime.
Documentation: Type definitions serve as a form of documentation, making it clear what data structures are expected.
IntelliSense Support: Enhanced IDE support, offering autocompletion and inline documentation.

## Typesafe API pattern

Create one file per endpoint following the pattern <endpoint><method>, in my case, it will be `ipGet`.
Manually test the API using curl, postman, or pure node fetch API

For example before testing the API:

```ts
export const ipGet = async (): Promise<any> => {
  const url = 'https://ifconfig.me/all.json';

  const options = {
    method: 'GET',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  };

  const response = await fetch(url, options);
  return await response.json();
}
```

After testing the API you can get a few JSON response examples, so you can properly type the function.

This is the JSON of the API above

```json
{
  "ip_addr": "2804:",
  "remote_host": "unavailable",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
  "port": "45180",
  "language": "en-US,en;q=0.9,pt;q=0.8,und;q=0.7,fr;q=0.6",
  "method": "GET",
  "encoding": "gzip, deflate, br, zstd",
  "mime": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
  "via": "1.1 google",
  "forwarded": "2804:"
}
```

Go to [https://transform.tools/json-to-typescript](https://transform.tools/json-to-typescript) to transform the JSON into a Typescript type


![typescript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs7gx34ckjfc6xt3mxg5.png)

The final code with the proper types would be:

```ts
export type Result = {
  ip_addr: string
  remote_host: string
  user_agent: string
  port: string
  language: string
  method: string
  encoding: string
  mime: string
  via: string
  forwarded: string
}
export const ipGet = async (): Promise<Result> => {
  const url = 'https://ifconfig.me/all.json';

  const options = {
    method: 'GET',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  };

  const response = await fetch(url, options);
  return await response.json();
}
```

You should also type the body of the request for POST and PUT.
Also, type the query string if any.


## In Conclusion
Following this simple structure, you are going to have a better DX to consume external HTTP requests in a typesafe way.
I would also save some examples of JSON in a `fixtures` directory to make it easy to write automated tests using `jest-fetch-mock`

---
[Woovi](https://www.woovi.com) is an innovative startup revolutionizing the payment landscape. With Woovi, shoppers can enjoy the freedom to pay however they prefer. Our cutting-edge platform provides instant payment solutions, empowering merchants to accept orders and enhance their customer experience seamlessly.

If you're interested in joining our team, we're hiring! Check out our job openings at [Woovi Careers](https://woovi.com/jobs/).

---
Photo by <a href="https://unsplash.com/@walkator?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Walkator</a> on <a href="https://unsplash.com/photos/a-close-up-of-a-computer-screen-with-a-lot-of-text-on-it-dwigDz0t6TY?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>