Typescript: Typing Your API Requests - Generics Hacks #4
Published: 2023-06-14 07:13:08

Are you ready to take your REST API requests to the next level? Buckle up, because… Ah! 😑 why go boring? while i can call u guyzzzzz 🤣


Btw, do you know? Along this short series, TypeScript and typing cases had come to a closer place to us, and are about to become that handy that do a lot of magic by a few tricks! 🙂

This is not generics-related tut but it's extending on the last Generics Hacks article.. we will use TypeScript generics to provide a  type-safe response coming from REST API requests whatever they were.

---

## TypeScript's UNKNOWN = The New Way of Knowing Things. 

We'll be using `fetch` API in this example, and will be using dummyjson.com to fetch dummy data for demonstration:

> Notes will precede code blocks … you can check out the code first and then read the notes.

1. Setting some variables for making API requests.

```typescript

// STEP 1
// setting variables
const url:string = "https://dummyjson.com";
const endPoint: string = "/users"
// u could use /posts or /products for other data types

```

2. This is the function where we request data…

* Promise<unknown> leverage the use of one of the primitive types in Typescript `unknown` 

* `unknown` is way safer than any that mist typing and make 

* `unknown` is so useful for APIs when you need to perform type checking before you use them.

* In contrast to any which means disable type checking `unknown` is a Typescript real and capable type, it's just 
the least effective among the more-specific others.

* The real power of unknown typing value is that you can use type guards to narrow the type and get more accurate type-checking on narrowed types.

```typescript

// STEP 2
async function GetAllItems(
  url: string, endpoint: string
): Promise<unknown> {
  const response = await fetch(url + endpoint);
  const json = await response.json();
  return json.users 
}

```

3. 🔥 **A TRICK** 🔥: now we declare an example user object w/ some/all properties. We will use that obj. to prototype that as our new base type User for that API call result

```typescript

// STEP 3
const userExample = {
  id: '',
  firstName: '',
  lastName: '',
}
type User = typeof userExample

```


4. Here we goooo.. one more step before sending our request:

* We are making a type-checker function based on the base-type `User` 

* The checker will take a user as a param to check on its type
* And will return the result narrowed using the Type-gaurd operator `is`

* So if user passes the checker and evaluates to => true

* That will enforce our typing for `intellisense` and type-safe use for all users

```typescript

// STEP 4
function isUser(user: any): user is User {
  // defaulting to false for effective checking
  let checking = false
  // iterating over keys from the `userExample` as they r the same keys for `User`
  for(const t of Object.keys(userExample)){
   checking = t in user
    if(!checking)
      return false
  }
  // if only one key evaluetes false 👆 user fails the test
  // otherwise it passes and return true 👇 and pass the success status to all the array result of users
  return checking
}

```


5. Now we call our API endpoint and return:

```typescript

// STEP 5
SendReq()
async function SendReq(
): Promise<User | null> {
  const allUsers:any = await GetAllItems(url, endPoint) // allUsers as `any` here to bypass the linter and we r about to check the type ourselves
  const user = allUsers[0] 
  if (user && isUser(user)) {
    console.log(user)
    // now user is typed and can be used safely 
    return allUsers; 
  }
  return null; // in case isUser(user) checking fails
}

```


➕**…and intellisense is working** 🟢


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




🟢🟢 Check out the full example code in the Typescript playground (try it urself)

{% embed https://www.typescriptlang.org/play?#code/PTAEGUBUFEAVQIwCgSgM4FMAuWCWA7Ac1ADcBDAJ1zICMAbDNJAYwHt80tQBXCugLk5UioALygARAAscABzT8QAE24BbVQE8AVmnYA6NqokBuFu06gM+JbFYEs-dFmHFxE4N0wU0ElGG6gbNx0SjyYoMCyrJxooKwUEbIUrCrMWLEAZvFxWFIYCUpkWGSgWBqyjEhVqFBwoABMSGRoGvjMoBncbXjsoADi2ACCdHQAklgYqmgAFEigPHyOQgSEADSW1lH2S84rSACUjrDJqriYADxdANb4rADu+AB8oADec4HmXBSMURwYYqAyHcyLguBlsMwpNNeHRQABqDZKLb4LD7UzzNgcLg6XriIEgr4-cwYPQ4-DTNHvb5YXj4UBkvSefKxJAAXyqfggMHgAGYzFiwvloAAPMiqWQMAFvea4JSOADk8tW7wyuG8WAAcmKMAqle86M1Ndrdcr2WUKqAAKpeAHmjCsDKCigisUSjAczm1eAAFk5uX+kIwzCu+VAd1wI1KZBDgKdgNiZDpskoYtKrECeWDcTpoNids5idC4cj1NppTyoG+aGCXHwlGSdwwoU8K3L-0g5QwAFpCGReKFWBUKEVsgADM6jzm6UC4R1MhLJtCYPMVwPB0OFyzkOjcIqMNNiZ7Obju1C5IphiOwqxZCjMf6sXilcqt28zlEYEZnKzhTd2rtoGQ4KCh02RkJG85MJ03S4L0ZzWvk0JeI4iYaIccZnFaNrShEYBKBgGR9nQeAiFg6aEXQ4RvgR4JpLgJABpmVx7PMDBcGuzEiOIFGYO8qCgvkRStqwDEJCGGiZCcbagKO84uuKDCjvGbYaJW0mAao-ziZkY4IRQk7zLe0yYhYXAOqAADyNBaEGWB6NpSFCqKCkYPs+w4RmQaca4pTvk67wyhk0wAIQcSs+wBfMlbYGWPHuvM7LzPxjrsHQqnsFpGCqRg24nhMmTgeEgC8G4AYjtxoREYrv8+VYHxYCsP6FDhuEoKgIuy6AtY0U0hQdLHv8RWAOI7nWhO16ncMw95Lk4RSeAe4Gwv6gIUMOqlVjWcRzl4TDzKWvWecGezsp63KgAArEg4BWEoABKGAAI4Uk0LRtB0XR0b0V3WHdj0HEcJzfucemgAAPqA+DBHQzxvKgtx3GGAYLXET6DLAoyIsiXCbnt+D8JywN2tm6BBlNTCw5Dz4Wr0FV0O8JlYyMekKKhAL4q1AxYMMYwTFM0J8Os122PY+y4YCjPbcpo6oUpeTfAeNDlM0VWgHQ9gbl1jZqbQj5cGRB1XNJhOPt4n4MTtHwCvOrPi8yADaAAMAC6oDvLOoCOQkABknszmgeke25ryRSZrAMHodCsIQAeRbD9wYXmnahJuzCJqAND-EyoSAeCaUu1F3VlgtTPGHnoCJQX+0QyMJf8XSKctX7XgB-rr4gpRbJAA %}

🟢🟢 Check out the full example code gist:

{% embed  https://gist.github.com/taricov/6a5d4d4e8825318c9755950341a95dc8 %}