Making REST API calls with TypeScript (With Examples)

This post describes how to make API calls in Typescript, and how we can support types and interfaces while calling REST APIs.

If you just want to see the code, go here

Typescript helps developers by providing static analysis and autocomplete features for their Javascript code. When calling REST APIs, the response is normally in a serialized format, most commonly JSON.

We can then divide the process of integration API calls with Typescript into two parts:

  1. Assigning a type to the API call itself
  2. Assigning a type to the API response

As an example, let's consider a REST API endpoint to get a list of users with their name and age.

The API response will be in JSON format:

[
        {
                "name": "Lorem",
                "age": 20
        },
        {
                "name": "Ipsum",
                "age": 18
        },
        {
                "name": "Dolor",
                "age": 35
        }
]

Let's illustrate how we can support Typescript while making a REST API call to get the above list of users.

Creating an interface for the API response

Since we want a list of users, let's create an interface for them.

interface User {
        name: string
        age: string
}

For now, we'll make a simple interface with the name and age fields corresponding to the data.

Assigning a type to the API call

In order to make the API call, we will use the browsers fetch API, which returns a Promise type.

For most use cases, API calls are wrapped in functions to encapsulate the API call itself. For us, this function will return a Promise that resolves to an array of User types:

function getUsers(): Promise<User[]> {
        // Code for fetching users goes here
}

Assigning a type to the API response

Let's fill in the getUsers function with the code for the API call:

function getUsers(): Promise<User[]> {
        // For now, consider the data is stored on a static `users.json` file
        return fetch('/users.json')
                // the JSON body is taken from the response
                .then(res => res.json())
                .then(res => {
                        // The response has an `any` type, so we need to cast
                        // it to the `User` type, and return it from the promise
                        return res as User[]
                })
}

The important thing to remember is to cast the response type to the type you are expecting, and return it from the Promise callback. Without these two steps, the Typescript compiler will give you an error, since the getUers function is supposed to return a Promise<User[]> type.

Usage and Examples

Let's take a look at the complete code for the above example, to fetch the list of users, and assign their names to an element in our HTML document:

interface User {
        name: string
        age: string
}

function getUsers(): Promise<User[]> {

        // For now, consider the data is stored on a static `users.json` file
        return fetch('/users.json')
                // the JSON body is taken from the response
                .then(res => res.json())
                .then(res => {
                        // The response has an `any` type, so we need to cast
                        // it to the `User` type, and return it from the promise
                        return res as User[]
                })
}

const result = document.getElementById('result')
getUsers()
        .then(users => {
                result.innerHTML = users.map(u => u.).toString()
        })

When we call the getUsers function, Typescript knows that we're supposed to get back a list of User types, and so we can make use of type annotations:

example with type annotations

as well as autocomplete:

example with autocompletion

I use VSCode as my editor, but Typescript annotations and autocompletion features are present in most popular text editors.

If you want to see the complete working example, you can find the code on Github


Liked this article? Share it on: