Using fetch with Typescript and Todoist

Ricardo Trindade
ITNEXT
Published in
3 min readApr 25, 2020

--

I’ve been playing around with Typescript these days. And so far the experience has been pretty great. I’ve worked mostly with Ruby, Kotlin. I’ve also used Javascript on a few occasions. That said I didn’t find the change to Typescript as hard as I thought, in fact, I find it quite intuitive. As I’ve been using it with VScode (also built-in Typescript), the IDE often points out any missing/wrong types, that would prevent countless hours of debugging.

In the javascript projects that I’ve worked in the past for making HTTP requests, I would use libs like Axios or $.ajax, which got me thinking what if I could use the recent fetch API instead. Using fetch eliminates the need for an external dependency like Axios or jQuery, although as of today, not all browsers support it (looking at you Internet Explorer).

So I decided to try both Typescript and fetch together in a simple react app. I will use Todoist’s Tasks API for this example (API Docs: https://developer.todoist.com/rest/v1/#tasks). The example will consist of creating a simple task via the API. For those who don’t know, Todoist is a productivity app that lets you organize, plan, and collaborate on tasks and projects. Personally, I use its task lists to organize my day at work, and also for as a shopping list whenever I need to do grocery shopping.

To use the API you need to get a token which can be obtained by creating an account.

To create a task via the API is pretty straightforward, you need to make a POST request, with some params, and also pass in a couple of headers as it is described below.

To set headers with fetch you can use the type HeadersInit as shown below

import { v4 as uuidv4 } from 'uuid';const headers: HeadersInit = {
'Content-Type': 'application/json',
'X-Request-Id': uuidv4(),
'Authorization': `Bearer <API_TOKEN>`
}

As for the request body, I’ve declared a type called TaskParam shown below

export type TaskParam = {
content: string;
due_lang: string;
due_string: string;
priority: number
};
const taskParam: TaskParam = {
content: 'Buy eggs',
due_string: 'Tomorrow at 12.00',
due_lang: 'en',
priority: 1,
}

And finally to make the request here how you can do it:

export async function createTask(taskParam: TaskParam): Promise<Response> {
const url = 'https://api.todoist.com/rest/v1/tasks';
const opts: RequestInit = {
method: 'POST',
headers,
body: JSON.stringify(taskParam),
};
return fetch(url, opts)
}

And that’s it, you should be able to re-use this function to create as many tasks as you’d like.

If instead, we are looking into getting all active tasks, the code is very similar.

export async function getTasks(): Promise<Response> {
const url = 'https://api.todoist.com/rest/v1/tasks';
const opts: RequestInit = {
method: 'GET',
headers,
};
return fetch(url, opts)
}

As for testing, you need to add fetch-mock to your package.json. Here’s an example snippet of a test written in jest.

import fetchMock from 'fetch-mock';const taskParam: TaskParam = {
content: 'Buy eggs',
due_string: 'Tomorrow at 12.00',
due_lang: 'en',
priority: 1,
}
describe('createTask', () => {
it('returns ok', async () => {
fetchMock.post('https://api.todoist.com/rest/v1/tasks', { ok: 'ok' });const response = await createTask(taskParam);
const result = await response.json()
expect(result).toEqual({ ok: "ok" });});
});

Overall the code may look pretty similar to Javascript but when using Typescript the IDE may point out some fields that may be missing in the response body, headers, or overall request config.

Enjoyed the story? Check out some more on my personal website https://www.ricardo-trindade.com/

--

--

Writer for

Fullstack engineer at Marley Spoon. Keen interest in machine learning, Ruby and Kotlin