Package Exports
- guardz
- guardz/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (guardz) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
🛡️ Guardz
Lightweight, zero-dependency TypeScript type guards for runtime validation with structured error handling.
The easiest way to add runtime type safety to your TypeScript projects — works with React, Angular, Vue, Node.js, and more. No complex schemas, no heavy dependencies.
Perfect for: React form validation, Node.js API validation, TypeScript runtime type checking, Express middleware validation, Next.js server-side props, Angular services, Vue.js composition API, and any TypeScript project needing lightweight runtime validation.
📋 Table of Contents
- 🚀 Quick Start
- ✨ Features
- 📦 Installation
- 🎯 Core Concepts
- 📖 Examples
- 🔧 API Reference
- ⚡ Performance
- 🌐 Ecosystem
- 🤝 Contributing
🚀 Quick Start
Get started in 30 seconds:
import { isType, isString, isNumber } from 'guardz';
// Define your type guard
const isUser = isType({
name: isString,
age: isNumber,
});
// Validate data
const data: unknown = { name: 'John', age: 30 };
if (isUser(data)) {
// TypeScript knows this is safe
console.log(data.name.toUpperCase()); // ✅ Works
console.log(data.age.toFixed(2)); // ✅ Works
}
With error handling:
const errors: string[] = [];
const config = {
identifier: 'user',
callbackOnError: (error: string) => errors.push(error),
};
const invalidData = { name: 'John', age: '30' }; // age should be number
isUser(invalidData, config);
// errors: ['Expected user.age ("30") to be "number"']
✨ Features
🎯 Core Benefits
- 🚀 Zero Setup - Import and use immediately
- 📦 Ultra Lightweight - ~1.7KB gzipped, zero dependencies
- 🎯 TypeScript Native - Perfect type inference and safety
- 🛡️ Structured Errors - Know exactly what failed and why
- ⚡ Performance Optimized - Choose the right error mode for your use case
🔧 Advanced Features
- 📊 JSON Tree Feedback - Comprehensive validation analysis
- 🎛️ Multiple Error Modes - Single, multi, and JSON tree modes
- 🌐 Ecosystem Integration - Event handling, HTTP clients, code generation
- 🔍 Nested Validation - Deep object and array validation
- 📝 Template Literal Support - Easy debugging and logging
- 🚀 Framework Agnostic - Works with React, Angular, Vue, Node.js, and more
📦 Installation
npm install guardz
# or
yarn add guardz
# or
pnpm add guardz
Bundle Size
- Gzipped: ~1.7KB
- Uncompressed: ~11.7KB
- Dependencies: Zero
🎯 Core Concepts
Structured Error Handling
Guardz's most important feature is its structured error reporting:
- What failed (the value and its field)
- Where it failed (the property path)
- What was expected (the type or constraint)
// Clear, actionable error messages
"Expected user.age ("30") to be "number""
"Expected user.details.email (123) to be "string""
"Expected users[2].isActive (null) to be "boolean""
Error Modes
Guardz supports three error modes optimized for different use cases:
Multi Mode (Default)
Collects all validation errors in a single combined message:
const config = {
identifier: 'user',
callbackOnError: (error: string) => console.log(error),
// errorMode: 'multi' (default)
};
// Output: "Expected user.name (123) to be "string"; Expected user.age ("30") to be "number""
Best for: General validation, user feedback, and debugging scenarios.
Single Mode
Stops validation at the first error for maximum performance:
const config = {
identifier: 'user',
callbackOnError: (error: string) => console.log(error),
errorMode: 'single' as const,
};
// Output: "Expected user.name (123) to be "string""
Best for: Performance-critical scenarios and fail-fast validation.
JSON Tree Mode
Provides structured JSON feedback with complete validation state:
const config = {
identifier: 'user',
callbackOnError: (error: string) => console.log(error),
errorMode: 'json' as const,
};
// Output: Complete JSON tree with valid/invalid branches
Best for: Complex DTOs with related fields, monitoring systems, and comprehensive analysis.
Performance Considerations
Mode | Performance | Use Case |
---|---|---|
Single | Fastest | High-frequency validation, API validation |
Multi | Moderate | General validation, form validation |
JSON Tree | Highest overhead | Complex analysis, monitoring systems |
📖 Examples
Basic Object Validation
import { isType, isString, isNumber, isBoolean } from 'guardz';
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
const isUser = isType<User>({
id: isNumber,
name: isString,
email: isString,
isActive: isBoolean,
});
// Usage
const userData: unknown = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
isActive: true,
};
if (isUser(userData)) {
// TypeScript knows this is a User
console.log(userData.name.toUpperCase());
}
Nested Object Validation
import { isType, isString, isNumber, isArray } from 'guardz';
const isAddress = isType({
street: isString,
city: isString,
zipCode: isString,
});
const isUserProfile = isType({
name: isString,
age: isNumber,
address: isAddress,
phoneNumbers: isArray(isString),
});
// Validates deeply nested structures
const profileData = {
name: 'Jane',
age: 30,
address: {
street: '123 Main St',
city: 'New York',
zipCode: '10001',
},
phoneNumbers: ['555-1234', '555-5678'],
};
if (isUserProfile(profileData)) {
// Fully typed access
console.log(profileData.address.city);
}
Array Validation
import { isType, isString, isNumber, isArray } from 'guardz';
const isStringArray = isArray(isString);
const isNumberArray = isArray(isNumber);
const isUserList = isType({
users: isArray(isType({
name: isString,
age: isNumber,
})),
totalCount: isNumber,
});
// Validates array contents
const userList = {
users: [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
],
totalCount: 2,
};
Union Types
import { isType, isString, isNumber, isOneOf } from 'guardz';
const isStatus = isOneOf(['active', 'inactive', 'pending'] as const);
const isId = isOneOf([isString, isNumber]); // string or number
const isEntity = isType({
id: isId,
status: isStatus,
name: isString,
});
Error Handling with Configuration
import { isType, isString, isNumber } from 'guardz';
const errors: string[] = [];
const config = {
identifier: 'api_response',
callbackOnError: (error: string) => errors.push(error),
errorMode: 'multi' as const, // default
};
const isApiResponse = isType({
status: isString,
data: isType({
id: isNumber,
name: isString,
}),
});
const invalidResponse = {
status: 200, // should be string
data: {
id: '123', // should be number
name: 456, // should be string
},
};
isApiResponse(invalidResponse, config);
// errors: [
// 'Expected api_response.status (200) to be "string"; Expected api_response.data.id ("123") to be "number"; Expected api_response.data.name (456) to be "string"'
// ]
JSON Tree for Monitoring
import { isType, isString, isNumber } from 'guardz';
const config = {
identifier: 'user',
callbackOnError: (error: string) => {
const errorTree = JSON.parse(error);
// Send to monitoring system
monitoringService.captureError({
type: 'validation_error',
data: errorTree,
timestamp: new Date().toISOString(),
});
},
errorMode: 'json' as const,
};
const isUser = isType({
name: isString,
age: isNumber,
});
const invalidUser = {
name: 123, // should be string
age: '30', // should be number
};
isUser(invalidUser, config);
// Sends structured JSON tree to monitoring system
Framework Integration Examples
React & Next.js
import { isType, isString, isNumber } from 'guardz';
// Form validation in React
const isFormData = isType({
email: isString,
password: isString,
age: isNumber,
});
const handleSubmit = (formData: unknown) => {
const errors: string[] = [];
const config = {
identifier: 'form',
callbackOnError: (error: string) => errors.push(error),
};
if (isFormData(formData, config)) {
// TypeScript knows this is safe
console.log('Valid form data:', formData.email);
} else {
console.log('Validation errors:', errors);
}
};
// API response validation in Next.js
const isApiResponse = isType({
data: isType({
users: isArray(isType({
id: isNumber,
name: isString,
})),
}),
});
export async function getServerSideProps() {
const response = await fetch('/api/users');
const data: unknown = await response.json();
if (isApiResponse(data)) {
return { props: { users: data.data.users } };
}
return { props: { users: [] } };
}
Angular
import { isType, isString, isNumber } from 'guardz';
// Service with type validation
@Injectable()
export class UserService {
private isUser = isType({
id: isNumber,
name: isString,
email: isString,
});
async getUser(id: number): Promise<User | null> {
try {
const response = await this.http.get(`/api/users/${id}`).toPromise();
const data: unknown = response;
if (this.isUser(data)) {
return data; // Fully typed as User
}
console.error('Invalid user data received');
return null;
} catch (error) {
console.error('Failed to fetch user:', error);
return null;
}
}
}
Vue.js
import { isType, isString, isNumber } from 'guardz';
// Composition API with validation
export function useUserValidation() {
const isUser = isType({
id: isNumber,
name: isString,
email: isString,
});
const validateUser = (data: unknown): User | null => {
const errors: string[] = [];
const config = {
identifier: 'user',
callbackOnError: (error: string) => errors.push(error),
};
if (isUser(data, config)) {
return data;
}
console.error('Validation errors:', errors);
return null;
};
return { validateUser };
}
// In your Vue component
export default {
setup() {
const { validateUser } = useUserValidation();
const handleUserData = (data: unknown) => {
const user = validateUser(data);
if (user) {
// TypeScript knows this is a valid User
console.log(user.name);
}
};
return { handleUserData };
},
};
Node.js & Express
import { isType, isString, isNumber } from 'guardz';
// Express middleware for request validation
const isCreateUserRequest = isType({
body: isType({
name: isString,
email: isString,
age: isNumber,
}),
});
const validateUserRequest = (req: Request, res: Response, next: NextFunction) => {
const errors: string[] = [];
const config = {
identifier: 'request',
callbackOnError: (error: string) => errors.push(error),
};
if (isCreateUserRequest(req, config)) {
// TypeScript knows req.body is properly typed
console.log('Valid request body:', req.body.name);
next();
} else {
res.status(400).json({ errors });
}
};
// API route with validation
app.post('/users', validateUserRequest, (req: Request, res: Response) => {
// req.body is guaranteed to be valid
const { name, email, age } = req.body;
// Create user logic...
});
🔧 API Reference
Core Type Guards
Object Validation
isType<T>(schema)
- Validate objects against a schemaisObject
- Check if value is a plain objectisObjectWith<T>(properties)
- Validate object has specific properties
Primitive Type Guards
isString
- Check if value is a stringisNumber
- Check if value is a numberisBoolean
- Check if value is a booleanisNull
- Check if value is nullisUndefined
- Check if value is undefinedisSymbol
- Check if value is a symbolisBigInt
- Check if value is a BigInt
Array Type Guards
isArray<T>(itemGuard)
- Validate arrays with item validationisArrayBuffer
- Check if value is an ArrayBufferisDataView
- Check if value is a DataView
Function Type Guards
isFunction
- Check if value is a functionisAsyncFunction
- Check if value is an async functionisGeneratorFunction
- Check if value is a generator function
Date & Time Type Guards
isDate
- Check if value is a Date objectisValidDate
- Check if value is a valid Date
Collection Type Guards
isMap<K, V>(keyGuard, valueGuard)
- Validate Map objectsisSet<T>(itemGuard)
- Validate Set objectsisWeakMap
- Check if value is a WeakMapisWeakSet
- Check if value is a WeakSet
RegExp Type Guards
isRegExp
- Check if value is a RegExp object
Error Type Guards
isError
- Check if value is an Error object
Union Type Guards
isOneOf<T>(values)
- Check if value matches one of several valuesisOneOfTypes<T>(guards)
- Check if value matches one of several type guards
Composite Type Guards
isIntersectionOf<T>(guards)
- Validate intersection types (A & B & C)isExtensionOf<T, U>(baseGuard, extensionGuard)
- Validate inheritance patterns
Nullable/Optional Type Guards
isNullOr<T>(guard)
- Check if value is null or matches typeisUndefinedOr<T>(guard)
- Check if value is undefined or matches typeisNilOr<T>(guard)
- Check if value is null/undefined or matches type
Special Type Guards
isAsserted<T>()
- Always returns true (for 3rd party types)isEnum<T>(enumObj)
- Check if value matches enum valuesisEqualTo<T>(value)
- Check if value exactly equals specific valueisGeneric<T>(guard)
- Create reusable type guard functions
Configuration
interface TypeGuardFnConfig {
callbackOnError: (error: string) => void;
identifier?: string;
errorMode?: 'single' | 'multi' | 'json';
}
callbackOnError
(required): Function called when validation errors occuridentifier
(optional): Prefix for error messageserrorMode
(optional): Controls error collection and formatting
⚡ Performance
Bundle Size
- Gzipped: ~1.7KB
- Uncompressed: ~11.7KB
- Tree-shakeable: Only import what you use
Runtime Performance
- Single Mode: Fastest - stops at first error
- Multi Mode: Moderate - validates all fields efficiently
- JSON Tree Mode: Highest overhead - builds complete validation tree
Benchmarks
npm run test:performance
🌐 Ecosystem
Guardz is part of a comprehensive ecosystem for type-safe development:
🎯 guardz-event
Safe event handling with type validation and security checks.
npm install guardz-event
🌐 guardz-axios
Type-safe HTTP client with runtime validation.
npm install guardz-axios
🔧 guardz-generator
Automatically generate type guards from TypeScript interfaces.
npm install guardz-generator
🚀 Developer Experience & AI Search Optimization
Why Developers Choose Guardz
🔍 AI Search Friendly:
- Framework Agnostic: Works seamlessly with React, Angular, Vue, Node.js, Express, Next.js, NestJS
- Build Tool Compatible: Optimized for Webpack, Vite, Rollup, esbuild, SWC
- Testing Framework Ready: Perfect for Jest, Vitest, Cypress, Playwright
- Cloud Platform Optimized: Deploy on AWS, Azure, GCP, Vercel, Netlify
- Modern Runtime Support: Compatible with Node.js, Deno, Bun
⚡ Performance Optimized:
- Tree-shakeable: Only import what you use
- Bundle size optimized: ~1.7KB gzipped
- Zero dependencies: No bloat, no conflicts
- Runtime efficient: Minimal overhead with smart error modes
🎯 Developer Productivity:
- Zero configuration: Works out of the box
- TypeScript native: Perfect type inference
- Familiar syntax: If you know TypeScript, you know Guardz
- Comprehensive examples: Real-world usage patterns for every framework
Search Keywords for AI & Developers
Guardz is optimized for discovery by AI search engines and developers looking for:
- "TypeScript runtime validation" - Core functionality
- "React form validation" - Frontend use cases
- "Node.js API validation" - Backend use cases
- "Type guards for Express" - Framework-specific needs
- "Lightweight validation library" - Performance-focused developers
- "Zero dependency type checking" - Bundle size conscious teams
- "TypeScript schema validation" - Alternative to Zod/Joi
- "Runtime type safety" - Core value proposition
- "API response validation" - Common use case
- "Form validation TypeScript" - Frontend validation needs
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
git clone https://github.com/thiennp/guardz.git
cd guardz
npm install
npm test
Code Style
- Follow existing code style and formatting
- Add tests for new features
- Update documentation as needed
📄 License
MIT License - see LICENSE file for details.
🚀 Ready to Get Started?
Guardz makes runtime type safety incredibly simple. No complex setup, no heavy dependencies, just pure TypeScript goodness.
import { isType, isString, isNumber } from 'guardz';
// That's literally it. You're ready to go.
const isUser = isType({ name: isString, age: isNumber });
Why developers love Guardz:
- 🚀 Zero friction - Works immediately, no configuration needed
- 📦 Ultra lightweight - ~1.7KB gzipped, zero dependencies
- 🎯 TypeScript native - No generated types, no complex schemas
- 🔧 Drop-in ready - Works with your existing code
- 🛡️ Smart defaults - Multi-mode error handling for better UX out of the box
- ⚡ Performance optimized - Choose the right error mode for your use case
- 🌐 Framework agnostic - Works with React, Angular, Vue, Node.js, and more
- 🔍 AI search optimized - Easy to discover and integrate
📞 Support
- 📖 Documentation - This README contains comprehensive examples
- 🐛 Issues - Report bugs on GitHub Issues
- 💬 Discussions - Ask questions on GitHub Discussions
Show Your Support
- ⭐ Star the repository on GitHub
- 🍺 Buy me a beer - PayPal
- 📢 Share with your team and community