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 example 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:
- Assigning a type to the API call itself
- 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:
as well as autocomplete:
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