Typescript: Typing Your API Requests — Generics Hacks #4

Taric Ov
3 min readJun 14, 2023

--

Typing a REST API Request

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.
// 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.
// 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

// 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
// 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:

// 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 🟢

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

🟢🟢 Check out the full example code gist:

--

--

Taric Ov
Taric Ov

Written by Taric Ov

software eng. 🎧 i build something new every week 🥷 samurai 😀 radio-ist @thesamuraination.com 🎙️ ai hassler 🤖