Last updated: Feb 27, 2024
Reading timeยท6 min
Let's look at examples of how to make HTTP requests in TypeScript.
If you want to use the axios
package to make HTTP requests in TypeScript,
check out my other article -
Making HTTP requests with Axios in TypeScript,
as this article uses the built-in fetch()
method.
node-fetch
package.If you are on the browser or use a more recent Node.js version, you don't have
to install or import node-fetch
as it is a built-in method.
You can check your version of Node with the node -v
command.
node -v
To install the node-fetch
package, open your terminal in the root directory of
your project and run the following 2 commands.
npm install node-fetch@2.6.7 npm install --save-dev @types/node-fetch@2.x
Here is an example of making an HTTP GET
request in TypeScript.
// ๐๏ธ only necessary if running in Node.js version < 17.5 // (Remove this line if running in the browser) import fetch from 'node-fetch'; type User = { id: number; email: string; first_name: string; }; type GetUsersResponse = { data: User[]; }; async function getUsers() { try { // ๐๏ธ const response: Response const response = await fetch('https://reqres.in/api/users', { method: 'GET', headers: { Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } // ๐๏ธ const result: GetUsersResponse const result = (await response.json()) as GetUsersResponse; console.log('result is: ', JSON.stringify(result, null, 4)); return result; } catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } } getUsers();
The first parameter we passed to the fetch() method is the URL of the resource.
const response = await fetch('https://reqres.in/api/users', { method: 'GET', headers: { Accept: 'application/json', }, });
The second parameter is an
options object,
where we set an HTTP header and the request method (GET
in the example).
fetch()
method doesn't reject a promise automatically on HTTP errors, so we have to check for the value of the response.ok
property.if (!response.ok) { throw new Error(`Error! status: ${response.status}`); }
The response.ok property contains a boolean value that states whether the response was successful or not.
If the response is successful, we have to call the
json method on
the Response
interface to parse
the JSON from the server into a native JavaScript object.
const result = (await response.json()) as GetUsersResponse;
We used a type assertion to set the type of the parsed response from the server.
In our catch()
method, we check if the error is an instance of the Error
object, so we can safely access the message
property.
catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } }
Otherwise, the error is typed as unknown
and we have to manually check its
type before accessing any properties.
Let's look at an example HTTP POST
request in TypeScript.
I'll post the entire code snippet and then we'll go over it.
Make sure to remove the fetch
import if running in the browser.
// ๐๏ธ only necessary if running in Node.js version < 17.5 // (Remove this line if running in the browser) import fetch from 'node-fetch'; type CreateUserResponse = { name: string; job: string; id: string; createdAt: string; }; async function createUser() { try { // ๐๏ธ const response: Response const response = await fetch('https://reqres.in/api/users', { method: 'POST', body: JSON.stringify({ name: 'John Smith', job: 'manager', }), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } // ๐๏ธ const result: CreateUserResponse const result = (await response.json()) as CreateUserResponse; console.log('result is: ', JSON.stringify(result, null, 4)); return result; } catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } } createUser();
Notice that we set the
http method
to POST
this time.
const response = await fetch('https://reqres.in/api/users', { method: 'POST', body: JSON.stringify({ name: 'John Smith', job: 'manager', }), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, });
JSON.stringify()
method to convert the object to a JSON string that we can send over the network.We also added the Content-Type
HTTP header to notify the server that the data
in the POST
request is a JSON string.
Make sure to always set the Content-Type
header to application/json
when
sending JSON data over the network, as you might get confusing errors if you
don't.
Let's look at an example HTTP PATCH
request made with fetch
in TypeScript.
// ๐๏ธ only necessary if running in Node.js version < 17.5 // (Remove this line if running in the browser) import fetch from 'node-fetch'; type UpdateUserResponse = { name: string; job: string; updatedAt: string; }; async function updateUser() { try { // ๐๏ธ const response: Response const response = await fetch('https://reqres.in/api/users/2', { method: 'PATCH', body: JSON.stringify({ name: 'John Smith', job: 'manager', }), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } // ๐๏ธ const result: UpdateUserResponse const result = (await response.json()) as UpdateUserResponse; console.log('result is: ', JSON.stringify(result, null, 4)); return result; } catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } } updateUser();
This time we set the method
property to PATCH
in the options object.
We still have to convert the request body to JSON by passing it to the
JSON.stringify()
method.
Notice that we set the Content-Type
header to application/json
just like we
did when making a POST
request.
The last step is to use a type assertion to set the type of the result
variable to the expected response type.
For completeness' sake, let's look at an example HTTP PUT
request made with
fetch
in TypeScript.
// ๐๏ธ only necessary if running in Node.js version < 17.5 // (Remove this line if running in the browser) import fetch from 'node-fetch'; type UpdateUserResponse = { name: string; job: string; updatedAt: string; }; async function updateUser() { try { // ๐๏ธ const response: Response const response = await fetch('https://reqres.in/api/users/2', { method: 'PUT', body: JSON.stringify({ name: 'John Smith', job: 'manager', }), headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } // ๐๏ธ const result: UpdateUserResponse const result = (await response.json()) as UpdateUserResponse; console.log('result is: ', JSON.stringify(result, null, 4)); return result; } catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } } updateUser();
The only thing that changed in the code sample is that we set the method
property in the options
object to PUT
instead of PATCH
.
Let's look at an example HTTP DELETE
request made with fetch
in TypeScript.
// ๐๏ธ only necessary if running in Node.js version < 17.5 // (Remove this line if running in the browser) import fetch from 'node-fetch'; async function deleteUser() { try { // ๐๏ธ const response: Response const response = await fetch('https://reqres.in/api/users/2', { method: 'DELETE', headers: { Accept: 'application/json', }, }); if (!response.ok) { throw new Error(`Error! status: ${response.status}`); } console.log('User deleted successfully'); return 'user deleted successfully'; } catch (error) { if (error instanceof Error) { console.log('error message: ', error.message); return error.message; } else { console.log('unexpected error: ', error); return 'An unexpected error occurred'; } } } deleteUser();
We set the method
property to DELETE
and removed the body
and the
Content-Type
header, because we aren't sending a request body with a DELETE
request.
const response = await fetch('https://reqres.in/api/users/2', { method: 'DELETE', headers: { Accept: 'application/json', }, });
204
- "No Content".Note that you shouldn't try to parse an empty response by calling the json()
method because you would get an error: "Unexpected end of JSON input" as the
response you're trying to parse has no response body.
You can learn more about the related topics by checking out the following tutorials: