Typed REST and HTTP Client
typed-rest-client is a lightweight REST and HTTP client library designed for Node.js, with a strong emphasis on TypeScript support, including generics and async/await capabilities. The current stable version is 2.3.0, building on a release history that includes a significant v2.0.0 update in late 2023 that raised the minimum Node.js requirement to version 16.0.0. The library provides built-in TypeScript typings, eliminating the need for separate type installations. It differentiates itself by offering both a low-level HttpClient, which returns response objects for all HTTP statuses (including 4xx/5xx), and a higher-level RestClient, which automatically deserializes JSON and throws errors for non-success status codes. Key features include support for Basic, Bearer, and NTLM authentication, proxy configurations, client/server certificates, and automatic handling of HTTP redirects. It maintains a regular, but not rapid, release cadence, focusing on stability and functionality for enterprise Node.js applications.
Common errors
-
Error [ERR_REQUIRE_ESM]: require() of ES Module ... typed-rest-client/RestClient.js not supported.
cause Attempting to use CommonJS `require()` syntax with `typed-rest-client` v2.x, which is an ESM-only package.fixSwitch to ES module `import` syntax: `import { RestClient } from 'typed-rest-client/RestClient';`. Ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json` or using `.mjs` file extension). -
RestClient threw an error for status 401: Failed Request: (401)
cause The `RestClient` received a 4xx or 5xx HTTP status code from the server (e.g., Unauthorized, Internal Server Error), causing it to throw an error.fixImplement proper error handling with `try...catch` blocks around `RestClient` calls to gracefully manage non-success HTTP responses. Inspect `err.statusCode` for the exact HTTP status and `err.message` for details. -
TypeError: Cannot read properties of null (reading 'id')
cause The `RestClient`'s `get` or `post` method returned `null` for `response.result` (e.g., on a 404 Not Found without an error body), and the code attempted to access properties on `response.result` without a null check.fixAlways check if `response.result` is not `null` or `undefined` before accessing its properties: `if (response.statusCode === 200 && response.result) { ... }`.
Warnings
- breaking Version 2.0.0 and above of `typed-rest-client` requires Node.js version 16 or higher. Older Node.js versions are not supported.
- gotcha The `HttpClient` and `RestClient` classes handle errors differently. `HttpClient` will return a response object for all HTTP status codes (e.g., 404, 500) and will not throw. `RestClient`, being higher-level, will automatically deserialize JSON and will throw an error for any 4xx or 5xx status codes (except often 404 with an empty body, where `result` will be `null`), making it crucial to use `try...catch` blocks.
- deprecated Version 1 of `typed-rest-client` is End-of-Life (EOL) and contains known security vulnerabilities. It should not be used in production environments.
- gotcha This package uses explicit subpath imports for its main classes (e.g., `/RestClient`, `/HttpClient`, `/Interfaces`). Attempting to import directly from the root package will result in module resolution errors.
Install
-
npm install typed-rest-client -
yarn add typed-rest-client -
pnpm add typed-rest-client
Imports
- RestClient
import { RestClient } from 'typed-rest-client'; const { RestClient } = require('typed-rest-client');import { RestClient } from 'typed-rest-client/RestClient'; - HttpClient
import { HttpClient } from 'typed-rest-client'; const { HttpClient } = require('typed-rest-client');import { HttpClient } from 'typed-rest-client/HttpClient'; - IRequestOptions
import { IRequestOptions } from 'typed-rest-client'; import { IRequestOptions } from 'typed-rest-client/RestClient';import { IRequestOptions } from 'typed-rest-client/Interfaces';
Quickstart
import { RestClient } from 'typed-rest-client/RestClient';
interface Todo {
userId: number;
id: number;
title: string;
completed: boolean;
}
async function fetchTodo() {
// The user-agent string is required for RestClient initialization
const rest = new RestClient('my-app-user-agent');
try {
const response = await rest.get<Todo>('https://jsonplaceholder.typicode.com/todos/1');
if (response.statusCode === 200 && response.result) {
console.log(`Fetched Todo (ID: ${response.result.id}): ${response.result.title} - Completed: ${response.result.completed}`);
} else if (response.statusCode === 404) {
// RestClient does not throw for 404 if no error body is returned and result will be null
console.log('Todo not found.');
} else {
console.error(`Request failed with status: ${response.statusCode}`);
}
} catch (err: any) {
// RestClient throws for other 4xx/5xx errors
if (err.statusCode) {
console.error(`RestClient threw an error for status ${err.statusCode}: ${err.message}`);
} else {
console.error(`An unexpected network or client error occurred: ${err.message}`);
}
}
}
fetchTodo();