mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmWeb Backendupdated 08 Aug 2026

typed-rest-client

typed-rest-client is a Node HTTP library from Microsoft with two levels. RestClient joins a base URL, serializes JSON bodies, parses JSON responses into TypeScript generic result shapes, and treats HTTP errors according to REST-oriented rules. HttpClient exposes status, headers, response streams, and raw bodies without throwing merely because a server returned 4xx or 5xx. Both can use pluggable Basic, Bearer, personal access token, and legacy NTLM handlers, plus proxies, client certificates, redirects, retries for read operations, and keep-alive agents.

Verdict

A defensible compatibility choice for existing Microsoft-flavored Node tooling that needs PAT auth, proxies, certificates, and CommonJS. New services making normal HTTP calls should prefer native fetch, undici, or got, and nobody should choose it today solely for the deprecated NTLM handler.

API stability3/5RestClient, HttpClient, handler subpaths, and their constructor shapes have existed for years, and v3 retains the familiar samples. The May 2026 major replaced deprecated URL parsing and updated dependencies, but no v3 GitHub release notes explain migration impact. There is also no exports map, error metadata is attached dynamically, and the README still describes v2 as current, all of which weakens the public contract.
Docs2/5The README clearly distinguishes REST and HTTP error behavior, lists auth and transport features, and points to runnable samples and tests. It does not provide a real option reference, retry table, redirect defaults, proxy details, certificate examples, disposal warning, or current v3 migration notes. As of version 3.0.0, its Node support section still calls v2 current and maintained, forcing users into source and tests for accurate behavior.
Maintenance4/5Version 3.0.0 was published on May 22, 2026, and the repository was pushed on August 3, 2026. Recent commits replaced deprecated url.parse usage and repeatedly upgraded qs and underscore to address vulnerabilities. GitHub reports 25 open issues and pull requests. Maintenance is credible, but the stale README, missing v3 release entry, and continued legacy NTLM code keep it below top marks.
Ecosystem4/5npm recorded 3,898,517 downloads for the measured week, reflecting heavy use in Microsoft and automation dependency trees despite only 681 repository stars. Bundled PAT, Bearer, Basic, proxy, certificate, and Azure-adjacent behavior cover enterprise cases that fetch wrappers often leave to custom agents. Outside CommonJS Node tooling, the ecosystem fit drops sharply because there is no browser, edge, or Web Request API surface.

Use it if

  • You maintain a Node service or automation tool in the Microsoft and Azure ecosystem where personal access token handlers and corporate proxies are common
  • You need one CommonJS-friendly client with JSON convenience plus direct access to Node IncomingMessage streams
  • You need explicit proxy credentials, proxy bypass rules, custom certificate authorities, or mutual TLS from file paths
  • You support Node 16 and want bundled declarations with a long-established async API rather than depending on newer native fetch behavior
Skip it if

Setup reality

npm install typed-rest-client includes declarations and requires Node 16 or newer; there are no peer dependencies or native builds. Choose the layer before writing error handling. RestClient parses JSON, resolves 404 with a null result, and throws for other 4xx or 5xx responses. HttpClient treats HTTP status as data and only throws for transport failures, leaving you to read the body and inspect message.statusCode. The imports are CommonJS-oriented subpaths such as typed-rest-client/RestClient, /HttpClient, and /Handlers, with no package exports map or browser build. A user-agent string is the first constructor argument. Socket timeout defaults to three minutes unless set, redirects are enabled with a maximum of 50, and HTTPS-to-HTTP downgrade is blocked unless explicitly enabled. Retries are off by default and, when enabled, cover only OPTIONS, GET, DELETE, and HEAD for selected network errors or 502, 503, and 504 responses; writes never retry. Bearer and PAT handlers avoid forwarding authorization to a different host unless you opt into cross-origin authentication. Explicit proxy config and HTTP_PROXY, HTTPS_PROXY, or NO_PROXY are supported. Certificate paths are read synchronously when the client is constructed, and ignoreSslError disables certificate verification rather than fixing trust. If keepAlive is true, call dispose() or agents remain open. Finally, TypeScript generics are assertions, deserializeDates converts every parseable string through a broad JSON reviver, and NODE_DEBUG=http can expose sensitive headers in logs.

Patterns

Fetch a typed JSON resourceget-typed-json

import * as restm from 'typed-rest-client/RestClient';

interface User { id: number; name: string }

const client = new restm.RestClient('inventory-service', 'https://api.example.com');
const response = await client.get<User>('/users/42');

if (response.result) {
  console.log(response.result.name);
}

A 404 resolves with result null, and User is only a compile-time assertion; validate the parsed object at a trust boundary.

Create a JSON resourcepost-json

interface CreatedUser { id: number; name: string }

const response = await client.create<CreatedUser>('/users', {
  name: 'Ada',
});

console.log(response.statusCode, response.result?.id);

create sends POST with application/json; update uses PATCH and replace uses PUT with the same JSON serialization behavior.

Encode query parameters and custom headerssend-query-parameters

const response = await client.get<User[]>('/users', {
  queryParameters: {
    params: { page: 2, role: ['admin', 'editor'] },
    options: { arrayFormat: 'repeat' },
  },
  additionalHeaders: { 'x-request-id': requestId },
});

Query encoding is provided by qs; the generic result is still not checked against User[] at runtime.

Attach bearer authenticationsend-bearer-token

import * as restm from 'typed-rest-client/RestClient';
import * as handlers from 'typed-rest-client/Handlers';

const auth = new handlers.BearerCredentialHandler(process.env.API_TOKEN!);
const client = new restm.RestClient(
  'deployment-tool',
  'https://api.example.com',
  [auth],
);

The handler does not forward Authorization after a redirect to another host unless cross-origin authentication is explicitly enabled.

Authenticate with a Microsoft-style PATsend-personal-access-token

import * as handlers from 'typed-rest-client/Handlers';

const auth = new handlers.PersonalAccessTokenCredentialHandler(
  process.env.AZURE_DEVOPS_PAT!,
);
const client = new restm.RestClient('build-tool', organizationUrl, [auth]);

The handler sends Basic credentials built from PAT:<token>; keep the token server-side and leave cross-origin forwarding disabled.

Use HttpClient when every status is datainspect-raw-response

import * as httpm from 'typed-rest-client/HttpClient';

const client = new httpm.HttpClient('health-checker');
const response = await client.get('https://api.example.com/health');
const body = await response.readBody();

console.log(response.message.statusCode, body);

HttpClient does not reject for 404 or 500; inspect statusCode before trusting or parsing the body.

Read RestClient error metadatahandle-rest-error

try {
  await client.update('/users/42', { name: 'Grace' });
} catch (error) {
  const failure = error as Error & {
    statusCode?: number;
    result?: unknown;
    responseHeaders?: Record<string, unknown>;
  };
  console.error(failure.statusCode, failure.message);
}

This catch does not handle 404 because RestClient resolves that status with a null result; other statuses above 299 reject.

Enable retries for read operationsretry-read-requests

const client = new httpm.HttpClient('catalog-reader', [], {
  allowRetries: true,
  maxRetries: 3,
  socketTimeout: 10_000,
});

const response = await client.get('https://api.example.com/catalog');

Retries cover OPTIONS, GET, DELETE, and HEAD for selected network errors or 502, 503, and 504; POST, PUT, and PATCH never retry.

Route requests through a proxyconfigure-http-proxy

const client = new httpm.HttpClient('corp-tool', [], {
  proxy: {
    proxyUrl: 'http://proxy.company.example:8080',
    proxyUsername: process.env.PROXY_USER,
    proxyPassword: process.env.PROXY_PASSWORD,
    proxyBypassHosts: ['^localhost$', '\.company\.internal$'],
  },
});

Bypass entries become regular expressions; the client can also read HTTP_PROXY, HTTPS_PROXY, and NO_PROXY from the process environment.

Load a custom CA and client certificateconfigure-mutual-tls

const client = new httpm.HttpClient('mtls-client', [], {
  cert: {
    caFile: '/etc/my-app/ca.pem',
    certFile: '/etc/my-app/client.pem',
    keyFile: '/etc/my-app/client-key.pem',
    passphrase: process.env.CLIENT_KEY_PASSPHRASE,
  },
  socketTimeout: 15_000,
});

Certificate files are read synchronously at construction; do not replace this with ignoreSslError, which disables verification.

Upload a file streamupload-stream

import { createReadStream } from 'node:fs';

const stream = createReadStream('/tmp/artifact.zip');
const response = await client.uploadStream<{ id: string }>(
  'PUT',
  '/artifacts/latest',
  stream,
  { additionalHeaders: { 'content-type': 'application/zip' } },
);

RestClient still expects the response body to be JSON; use HttpClient and response.message.pipe() for a streamed download.

Close keep-alive agentsdispose-keepalive-client

const client = new httpm.HttpClient('batch-worker', [], {
  keepAlive: true,
  maxSockets: 20,
});

try {
  await client.get('https://api.example.com/jobs');
} finally {
  client.dispose();
}

The source documentation requires dispose() when keepAlive is enabled; using the client after disposal throws.

Alternatives

PackageRegistryPick it when
undicinpmUse it for a modern Node HTTP client, standards-based fetch, pooling, streaming, and AbortSignal support without legacy auth handlers.
gotnpmUse it in ESM Node applications that want hooks, rich retry controls, pagination, streams, and polished error objects.
axiosnpmUse it when one promise API must work in browsers and Node and interceptors matter more than NTLM or low-level IncomingMessage access.