Type-safe HTTP client built on top of Axios with runtime validation using guardz. Part of the guardz ecosystem for comprehensive TypeScript type safety.
npm install guardz-axios
A type-safe HTTP client built on top of Axios with runtime validation using guardz 1.11.3+.
Guardz Axios transforms your HTTP requests into type-safe operations that automatically validate response data at runtime. Instead of manually checking response types and handling errors, you get:
- Automatic runtime validation of all response data
- Type-safe results with discriminated unions
- Comprehensive error handling with detailed feedback
- Multiple API patterns for different use cases
- Retry logic with configurable backoff strategies
- Tolerance mode for graceful degradation
``bash`
npm install guardz-axios guardz axios
This library is part of the Guardz ecosystem - a comprehensive TypeScript type guard solution designed to bring runtime type safety to your applications:
#### guardz - Core Type Guard Library
The foundation of the ecosystem, providing 50+ built-in type guards and utilities:
`bash`
npm install guardz
Features:
- 50+ built-in type guards for all JavaScript types
- Composite type guards for complex validation
- Custom type guard creation with isType() and isOneOf()isArrayOf()
- Array and object validation with and isRecord()isOptional()
- Optional and nullable types with and isNullable()isUnion()
- Union types with and isOneOf()isIntersection()
- Intersection types with
Example:
`typescript
import { isType, isString, isNumber, isOptional, isArrayOf } from "guardz";
interface User {
id: number;
name: string;
email?: string;
tags: string[];
}
const isUser = isType
id: isNumber,
name: isString,
email: isOptional(isString),
tags: isArrayOf(isString),
});
// Runtime validation
if (isUser(data)) {
// data is guaranteed to be User type
console.log(data.name); // Type-safe access
}
`
#### guardz-generator - Automatic Type Guard Generation
Automatically generate type guards from your TypeScript interfaces and types:
`bash`
npm install guardz-generator
Features:
- Automatic generation from TypeScript interfaces
- CLI tool for batch processing
- Watch mode for development
- Custom templates for specialized guards
- Integration with build tools and IDEs
Usage:
`bashGenerate guards from all TypeScript files
npx guardz-generator generate "src/*/.ts"
Generated Output:
`typescript
// Auto-generated from interface User
export const isUser = isType({
id: isNumber,
name: isString,
email: isOptional(isString),
tags: isArrayOf(isString),
});// Auto-generated from interface Post
export const isPost = isType({
id: isNumber,
title: isString,
content: isString,
author: isUser,
publishedAt: isOptional(isString),
});
`#### guardz-axios - Type-Safe HTTP Client
This package - a type-safe HTTP client with runtime validation:
`bash
npm install guardz-axios
`Features:
- Runtime validation of all HTTP responses
- Type-safe results with discriminated unions
- Multiple API patterns (curried, fluent, configuration-first)
- Retry logic with exponential backoff
- Tolerance mode for graceful degradation
- Comprehensive error handling
Example:
`typescript
import { safeGet } from "guardz-axios";
import { isUser } from "./guards"; // Generated by guardz-generatorconst result = await safeGet({ guard: isUser })("/users/1");
if (result.status === Status.SUCCESS) {
console.log(result.data.name); // Type-safe access
} else {
console.error(
Error: ${result.message});
}
`#### guardz-event - Type-Safe Event Handling
Type-safe event handling with runtime validation:
`bash
npm install guardz-event
`Features:
- Type-safe event emitters with runtime validation
- Event type guards for payload validation
- Event listeners with automatic type inference
- Event middleware for transformation and filtering
- Event history and replay capabilities
- Integration with Node.js EventEmitter and browser events
Example:
`typescript
import { createTypedEventEmitter } from "guardz-event";
import { isType, isString, isNumber } from "guardz";interface UserCreatedEvent {
userId: number;
userName: string;
}
const isUserCreatedEvent = isType({
userId: isNumber,
userName: isString,
});
const emitter = createTypedEventEmitter({
"user:created": isUserCreatedEvent,
});
// Type-safe event emission
emitter.emit("user:created", { userId: 1, userName: "John" });
// Type-safe event listening
emitter.on("user:created", (event) => {
console.log(
User created: ${event.userName} (ID: ${event.userId}));
// event is fully typed as UserCreatedEvent
});
`$3
The guardz ecosystem components work seamlessly together:
`typescript
// 1. Define your types
interface User {
id: number;
name: string;
email: string;
}// 2. Generate type guards automatically
// npx guardz-generator generate "src/*/.ts"
// This creates: src/guards/user.guards.ts
// 3. Use in HTTP requests
import { safeGet } from "guardz-axios";
import { isUser } from "./guards/user.guards";
const result = await safeGet({ guard: isUser })("/users/1");
// 4. Use in event handling
import { createTypedEventEmitter } from "guardz-event";
const emitter = createTypedEventEmitter({
"user:updated": isUser,
});
emitter.on("user:updated", (user) => {
// user is fully typed as User
console.log(
User updated: ${user.name});
});
`$3
1. Install the core packages:
`bash
npm install guardz guardz-generator guardz-axios guardz-event
`2. Set up automatic type guard generation:
`bash
# Add to package.json scripts
"scripts": {
"generate:guards": "guardz-generator generate \"src/*/.ts\"",
"watch:guards": "guardz-generator watch \"src/*/.ts\""
}
`3. Generate guards from your types:
`bash
npm run generate:guards
`4. Use in your application:
`typescript
import { safeGet } from "guardz-axios";
import { createTypedEventEmitter } from "guardz-event";
import { isUser, isPost } from "./guards"; // Auto-generated // Type-safe HTTP requests
const userResult = await safeGet({ guard: isUser })("/users/1");
// Type-safe event handling
const emitter = createTypedEventEmitter({
"user:created": isUser,
"post:published": isPost,
});
`$3
- guardz Documentation - Core type guard library
- guardz-generator Documentation - Automatic type guard generation
- guardz-axios Documentation - Type-safe HTTP client (this package)
- guardz-event Documentation - Type-safe event handling
$3
The guardz ecosystem is perfect for:
- API Development - Validate all incoming/outgoing data
- Event-Driven Applications - Type-safe event handling
- Microservices - Ensure data consistency across services
- Frontend Applications - Validate API responses and user input
- Backend Services - Validate database queries and external API calls
- Testing - Generate type-safe test data and mocks
$3
1. Define your types in TypeScript interfaces
2. Generate type guards automatically with guardz-generator
3. Use guards in your HTTP requests with guardz-axios
4. Handle events type-safely with guardz-event
5. Enjoy full runtime type safety across your application
Quick Start
`typescript
import { safeGet } from "guardz-axios";
import { isType, isString, isNumber } from "guardz";
import { Status } from "guardz-axios";interface User {
id: number;
name: string;
email: string;
}
const isUser = isType({
id: isNumber,
name: isString,
email: isString,
});
const result = await safeGet({ guard: isUser })("/users/1");
if (result.status === Status.SUCCESS) {
console.log("User:", result.data); // Fully typed as User
} else {
console.log("Error:", result.code, result.message);
}
`How It Works
$3
The library uses a discriminated union for type-safe results:
`typescript
type SafeRequestResult =
| { status: Status.SUCCESS; data: T }
| { status: Status.ERROR; code: number; message: string };
`$3
When the request succeeds and validation passes:
`typescript
{
status: Status.SUCCESS,
data: T // Your validated data
}
`$3
When the request fails or validation fails:
`typescript
{
status: Status.ERROR,
code: number, // HTTP status code or 500 for validation errors
message: string // Human-readable error message
}
`Error Types and Messages
$3
When response data doesn't match the expected type:
`typescript
{
status: Status.ERROR,
code: 500,
message: "Response data validation failed: Expected userData.id (\"1\") to be \"number\""
}
`$3
When network requests fail:
`typescript
{
status: Status.ERROR,
code: 500,
message: "Network Error"
}
`$3
When requests timeout:
`typescript
{
status: Status.ERROR,
code: 500,
message: "timeout of 5000ms exceeded"
}
`$3
When the server returns error status codes:
`typescript
{
status: Status.ERROR,
code: 404,
message: "Not Found"
}
`Error Handling Examples
$3
`typescript
const result = await safeGet({ guard: isUser })("/users/1");if (result.status === Status.SUCCESS) {
console.log("Success:", result.data);
} else {
console.error(
Request failed: ${result.message});
console.error(Status: ${result.code});
}
`$3
`typescript
const result = await safeGet({
guard: isUser,
tolerance: true,
onError: (error, context) => {
console.warn(Validation warning: ${error});
console.warn(Context: ${context.url} (${context.method}));
},
})("/users/1");if (result.status === Status.SUCCESS) {
console.log("Data is valid:", result.data);
} else {
console.log("Request failed:", result.message);
}
`$3
`typescript
const result = await safeRequest({
url: "/users/1",
method: "GET",
guard: isUser,
retry: {
attempts: 3,
delay: 1000,
backoff: "exponential",
},
});if (result.status === Status.SUCCESS) {
console.log("Request succeeded:", result.data);
} else {
console.error(
Request failed: ${result.message});
}
`$3
The library provides detailed error messages and multiple error handling strategies:
$3
1. Always check the status first:
`typescript
if (result.status === Status.SUCCESS) {
// Handle success
} else {
// Handle error
}
`2. Handle different error types appropriately:
`typescript
if (result.status === Status.ERROR) {
switch (result.code) {
case 404:
// Handle not found
break;
case 500:
// Handle server errors
break;
}
}
`3. Use tolerance mode for graceful degradation:
`typescript
const result = await safeGet({
guard: isUser,
tolerance: true,
})("/users/1"); if (result.status === Status.SUCCESS) {
// Use data confidently
} else {
// Handle error
}
`4. Use detailed error messages:
`typescript
const result = await safeGet({
guard: isUser,
onValidationError: (errors) => {
errors.forEach((error) => {
console.error(Validation failed: ${error});
});
},
})("/users/1");
`API Patterns
$3
Simple, functional approach:
`typescript
import { safeGet, safePost } from "guardz-axios";const getUser = safeGet({ guard: isUser });
const createUser = safePost({ guard: isUser });
const result = await getUser("/users/1");
if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`$3
Full control over request configuration:
`typescript
import { safeRequest } from "guardz-axios";const result = await safeRequest({
url: "/users/1",
method: "GET",
guard: isUser,
timeout: 5000,
retry: {
attempts: 3,
delay: 1000,
backoff: "exponential",
},
});
if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`$3
Chainable, readable API:
`typescript
import { safe } from "guardz-axios";const result = await safe()
.get("/users/1")
.guard(isUser)
.timeout(5000)
.retry({ attempts: 3, delay: 1000 })
.execute();
if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`$3
Shared configuration across requests:
`typescript
import { createSafeApiContext } from "guardz-axios";const api = createSafeApiContext({
baseURL: "https://api.example.com",
timeout: 5000,
defaultTolerance: true,
});
const result = await api.get("/users/1", { guard: isUser });
if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`Advanced Features
$3
Handle invalid responses gracefully:
`typescript
const result = await safeGet({
guard: isUser,
tolerance: true,
onError: (error, context) => {
console.warn(Validation warning: ${error});
},
})("/users/1");if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
} else {
console.log("Request failed:", result.message);
}
`$3
Automatic retry with exponential backoff:
`typescript
const result = await safeGet({
guard: isUser,
retry: {
attempts: 3,
delay: 1000,
backoff: "exponential",
retryOn: (error) => {
// Custom retry logic
return error.message.includes("network");
},
},
})("/users/1");if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`$3
Use your own Axios configuration:
`typescript
import axios from "axios";const customAxios = axios.create({
baseURL: "https://api.example.com",
headers: { Authorization: "Bearer token" },
});
const result = await safeGet({
guard: isUser,
axiosInstance: customAxios,
})("/users/1");
if (result.status === Status.SUCCESS) {
console.log("User:", result.data);
}
`Type Safety
$3
`typescript
const result = await safeGet({ guard: isUser })("/users/1");if (result.status === Status.SUCCESS) {
// TypeScript knows this is User
console.log(result.data.name); // ✅ Type-safe
console.log(result.data.email); // ✅ Type-safe
}
`$3
`typescript
import { isType, isString, isNumber } from "guardz";const isUser = isType({
id: isNumber,
name: isString,
email: isString,
});
const result = await safeGet({ guard: isUser })("/users/1");
``> 💡 Tip: Use guardz-generator to automatically generate type guards from your TypeScript interfaces instead of writing them manually!
See the examples directory for complete working examples:
- Basic Usage
- Advanced Patterns
- Quick Demo
- Error Handling Demo
Support this project by becoming a sponsor:
- GitHub Sponsors
- Open Collective
- Ko-fi
- Tidelift
- Liberapay
- IssueHunt
- Custom Sponsorship
MIT