Package Exports
- guardz-generator
- guardz-generator/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-generator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Guardz Generator
Guardz Generator is a powerful tool for automatically generating runtime type guards from your TypeScript interfaces and type aliases, using the guardz library. It enables robust runtime type checking for your TypeScript codebase with minimal effort.
What Can Guardz Generator Do?
- Generate Type Guards: Automatically creates type guard functions for your TypeScript interfaces, type aliases, enums, and more.
- Supports Generics: Handles generic interfaces and type aliases, including nested generics.
- Handles Recursion: Detects and supports both direct and indirect recursive types, generating correct function-based guards.
- Advanced Enum Support: Generates guards for enums using the
isEnum()pattern. - Union & Composite Types: Supports union types, intersection types, and complex compositions.
- Interface Extensions: Correctly handles interface inheritance with
isExtensionOfandOmittypes, properly filtering inherited properties. - Cross-file & NPM Types: Resolves and generates guards for types imported from other files or npm packages, using
local guards when available or falling back to
isAsserted. - Smart Import Path Resolution: Maintains consistency with your original import structure:
- Preserves relative imports:
'./models/User'→'./models/User.guardz' - Respects path aliases:
'@/types/ApiResponse'→'@/types/ApiResponse.guardz' - Handles global imports:
'@/global/_GlobalTypesToImport'→'@/global/isTypeName.guardz'
- Preserves relative imports:
- Post-Processing: Optionally formats, lints, and type-checks generated files for code quality.
- Flexible CLI & API: Use via CLI or programmatically in your own scripts.
- Full guardz 1.10.3 Support: Includes all utilities and enhanced error handling with comprehensive type checking capabilities.
Guardz Version Compatibility
Guardz Generator is fully compatible with guardz 1.10.3 and includes support for all features:
Core Type Guards
isString,isNumber,isBoolean,isDate: Basic type validationisAny,isUnknown: Universal type guardsisDefined,isNil: Null/undefined checkingisEnum: Enum validation
Advanced Type Guards
isType: Object structure validationisObjectWith: Object property validationisObject: Object type checkingisPartialOf: Partial object validationisNonNullObject: Non-null object validationisExtensionOf: Interface inheritance validationisIntersectionOf: Intersection type validation
Array & Collection Guards
isArrayWithEachItem: Array element validationisNonEmptyArray: Non-empty array validationisNonEmptyArrayWithEachItem: Non-empty array with element validationisTuple: Tuple validationisMap: Map validationisSet: Set validation
Number Guards
isInteger,isBigInt: Integer validationisPositiveNumber,isNegativeNumber: Sign validationisPositiveInteger,isNegativeInteger: Integer sign validationisNonNegativeNumber,isNonPositiveNumber: Non-negative/non-positive validationisNonNegativeInteger,isNonPositiveInteger: Integer range validation
String Guards
isNonEmptyString: Non-empty string validationisEqualTo: Equality validation
Union & Optional Guards
isOneOf: Union type validationisOneOfTypes: Multiple type validationisUndefinedOr,isNullOr,isNilOr: Optional type validation
Web API Guards
isFileList: FileList validationisBlob: Blob validationisFormData: FormData validationisURL: URL validationisURLSearchParams: URLSearchParams validationisFile: File validation
Function & Error Guards
isFunction: Function validationisError: Error validation
Advanced Features
guardWithTolerance: Tolerance-based validationisAsserted: Type assertion for external typesgenerateTypeGuardError: Enhanced error messages
Example Usage
export interface AdvancedUser {
id: number;
name: string;
email: string;
files: FileList;
metadata: Map<string, unknown>;
errors: Error[];
settings: Partial<{ theme: string; notifications: boolean }>;
}Generated:
import type { AdvancedUser } from './_AdvancedUser';
import type { TypeGuardFn } from 'guardz';
import {
isString,
isNumber,
isFileList,
isMap,
isArrayWithEachItem,
isError,
isPartialOf,
isType,
} from 'guardz';
export const isAdvancedUser: TypeGuardFn<AdvancedUser> = isType<AdvancedUser>({
id: isNumber,
name: isString,
email: isString,
files: isFileList,
metadata: isMap,
errors: isArrayWithEachItem(isError),
settings: isPartialOf<{ theme: string; notifications: boolean }>({
theme: isString,
notifications: isBoolean,
}),
});Installation
npm install guardz-generatorUsage
CLI
- Generate all type guards using a config file:
npx guardz-generator # or specify a config file npx guardz-generator --config guardz.config.ts
- Generate for specific files:
npx guardz-generator generate "src/**/*.ts" - Generate for a specific type:
npx guardz-generator generate "src/**/*.ts" -t UserDTO
- Skip post-processing:
npx guardz-generator generate "src/**/*.ts" --no-post-process
Programmatic API
import { GenerateTypeGuardsUseCase } from 'guardz-generator';
// Using the use case (recommended)
const useCase = new GenerateTypeGuardsUseCase();
const files = await useCase.execute(['src/**/*.ts']);
// Generate a specific type guard
const typeGuardCode = await useCase.executeForSpecificType(['src/**/*.ts'], 'UserDTO');
// Legacy API (still supported)
import { TypeGuardGenerator } from 'guardz-generator';
const generator = new TypeGuardGenerator(['src/**/*.ts']);
const files = generator.generateAllTypeGuards();
await generator.writeTypeGuardsToSameDirectory(files);
// Generate a specific type guard
const typeGuardCode = generator.generateTypeGuard('UserDTO');Supported TypeScript Features
Basic Types
- Interfaces & Type Aliases: Generates guards for all your interfaces and type aliases.
- Primitive Types:
string,number,boolean,bigint,symbol - Nullable & Optional Types: Correctly handles
null,undefined, and optional properties. - Arrays & Tuples: Generates guards for array and tuple types.
Advanced Types
- Generics: Handles generic types and nested generics with explicit type parameters.
- Enums: Generates guards using
isEnum(). - Union & Intersection Types: Full support for unions, intersections, and composite types.
- Recursive Types: Handles direct and indirect recursion, including multi-way cycles.
- BigInt & Advanced Number Types: Supports
bigintand advanced number types likePositiveInteger,NonNegativeInteger, etc. - Interface Extensions: Correctly handles interface inheritance with proper type guards, using
isExtensionOfandOmitto avoid duplicating inherited property checks.
Cross-File & External Types
- Cross-file & NPM Imports: Resolves types across files and npm packages, using local guards or
isAssertedas needed. - Smart Import Paths: Maintains your original import structure and path aliases.
Comprehensive Examples
1. Basic Interface
export interface User {
id: number;
name: string;
email?: string;
isActive: boolean;
}Generated:
import type { User } from './_User';
import type { TypeGuardFn } from 'guardz';
import { isNumber, isString, isUndefinedOr, isBoolean, isType } from 'guardz';
export const isUser: TypeGuardFn<User> = isType<User>({
id: isNumber,
name: isString,
email: isUndefinedOr(isString),
isActive: isBoolean,
});2. Interface Extensions
export interface Person {
name: string;
age: number;
}
export interface Employee extends Person {
employeeId: string;
department: string;
}
export interface Manager extends Employee {
managedTeamSize: number;
}Generated:
// isPerson.guardz.ts
export const isPerson: TypeGuardFn<Person> = isType<Person>({
name: isString,
age: isNumber,
});
// isEmployee.guardz.ts
export const isEmployee: TypeGuardFn<Employee> = isExtensionOf(
isPerson,
isType<Omit<Employee, keyof Person>>({
employeeId: isString,
department: isString,
}),
);
// isManager.guardz.ts
export const isManager: TypeGuardFn<Manager> = isExtensionOf(
isEmployee,
isType<Omit<Manager, keyof Employee>>({
managedTeamSize: isNumber,
}),
);Key Features:
- Uses
isExtensionOfto compose type guards - Uses
Omit<Interface, keyof Base>to only check additional properties - Avoids duplicating inherited property validations
- Supports multi-level inheritance chains
3. Generic Interfaces
export interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
totalPages: number;
currentPage: number;
}Generated:
// isApiResponse.guardz.ts
export const isApiResponse = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<ApiResponse<T>> =>
isType<ApiResponse<T>>({
data: typeGuardT,
status: isNumber,
message: isString,
});
// isPaginatedResponse.guardz.ts
export const isPaginatedResponse = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<PaginatedResponse<T>> =>
isExtensionOf(
isApiResponse(isArrayWithEachItem(typeGuardT)),
isType<Omit<PaginatedResponse<T>, keyof ApiResponse<T[]>>>({
totalPages: isNumber,
currentPage: isNumber,
}),
);4. Union Types
export type UserStatus = 'active' | 'inactive' | 'pending';
export type UserRole = 'admin' | 'user' | 'moderator';
export interface User {
id: number;
status: UserStatus;
role: UserRole;
permissions: (UserRole | 'super_admin')[];
}Generated:
export const isUserStatus = isOneOf('active', 'inactive', 'pending');
export const isUserRole = isOneOf('admin', 'user', 'moderator');
export const isUser: TypeGuardFn<User> = isType<User>({
id: isNumber,
status: isUserStatus,
role: isUserRole,
permissions: isArrayWithEachItem(
isOneOf('admin', 'user', 'moderator', 'super_admin'),
),
});5. Intersection Types
export interface HasId {
id: number;
}
export interface HasTimestamps {
createdAt: Date;
updatedAt: Date;
}
export type Entity = HasId & HasTimestamps;Generated:
export const isHasId: TypeGuardFn<HasId> = isType<HasId>({
id: isNumber,
});
export const isHasTimestamps: TypeGuardFn<HasTimestamps> =
isType<HasTimestamps>({
createdAt: isDate,
updatedAt: isDate,
});
export const isEntity: TypeGuardFn<Entity> = isIntersectionOf(
isHasId,
isHasTimestamps,
);6. Recursive Types
export interface TreeNode {
value: number;
children: TreeNode[];
}
export interface Comment {
id: string;
content: string;
replies: Comment[];
}Generated:
// isTreeNode.guardz.ts
export function isTreeNode(value: unknown): value is TreeNode {
return isType<TreeNode>({
value: isNumber,
children: isArrayWithEachItem(isTreeNode),
})(value);
}
// isComment.guardz.ts
export function isComment(value: unknown): value is Comment {
return isType<Comment>({
id: isString,
content: isString,
replies: isArrayWithEachItem(isComment),
})(value);
}7. Complex Types with Imports
import { AxiosResponse } from 'axios';
import { UserStatus } from '@/global/_GlobalTypesToImport';
export interface ApiUser {
id: number;
name: string | null;
status: UserStatus;
response: AxiosResponse;
metadata: {
lastLogin: Date;
preferences: Record<string, unknown>;
};
}Generated:
import type { AxiosResponse } from 'axios';
import { isUserStatus } from '@/global/isUserStatus.guardz';
import type { ApiUser } from './_ApiUser';
import type { TypeGuardFn } from 'guardz';
import {
isNumber,
isNullOr,
isString,
isType,
isDate,
isObjectWithEachItem,
isUnknown,
} from 'guardz';
export const isApiUser: TypeGuardFn<ApiUser> = isType<ApiUser>({
id: isNumber,
name: isNullOr(isString),
status: isUserStatus,
response: isAsserted<AxiosResponse>,
metadata: isType<{
lastLogin: Date;
preferences: Record<string, unknown>;
}>({
lastLogin: isDate,
preferences: isObjectWithEachItem(isUnknown),
}),
});8. Enum Types
export enum UserRole {
ADMIN = 'admin',
USER = 'user',
MODERATOR = 'moderator',
}
export enum OrderStatus {
PENDING = 'pending',
CONFIRMED = 'confirmed',
SHIPPED = 'shipped',
DELIVERED = 'delivered',
CANCELLED = 'cancelled',
}Generated:
export const isUserRole = isEnum(UserRole);
export const isOrderStatus = isEnum(OrderStatus);9. Advanced Number Types
export interface AdvancedNumbers {
positive: PositiveInteger;
nonNegative: NonNegativeInteger;
percentage: number; // 0-100
bigInt: bigint;
}Generated:
export const isAdvancedNumbers: TypeGuardFn<AdvancedNumbers> =
isType<AdvancedNumbers>({
positive: isPositiveInteger,
nonNegative: isNonNegativeInteger,
percentage: isNumber,
bigInt: isBigInt,
});10. Tuple Types
export type Coordinates = [number, number];
export type RGB = [number, number, number];
export type UserTuple = [string, number, boolean];Generated:
export const isCoordinates = isTuple(isNumber, isNumber);
export const isRGB = isTuple(isNumber, isNumber, isNumber);
export const isUserTuple = isTuple(isString, isNumber, isBoolean);11. Index Signatures
export interface StringMap {
[key: string]: string;
}
export interface NumberMap {
[key: string]: number;
}
export interface MixedMap {
[key: string]: string | number;
}Generated:
export const isStringMap = isObjectWithEachItem(isString);
export const isNumberMap = isObjectWithEachItem(isNumber);
export const isMixedMap = isObjectWithEachItem(isOneOf(isString, isNumber));12. Conditional Types
export type NonNullable<T> = T extends null | undefined ? never : T;
export type ArrayElement<T> = T extends Array<infer U> ? U : never;
export type PromiseType<T> = T extends Promise<infer U> ? U : never;Generated:
// Note: Conditional types are handled as their resolved types
// The generator will use the actual resolved type when possible
export const isNonNullable = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<NonNullable<T>> => isOneOf(typeGuardT, isNull, isUndefined);13. Mapped Types
export type Partial<T> = { [P in keyof T]?: T[P] };
export type Required<T> = { [P in keyof T]-?: T[P] };
export type Readonly<T> = { readonly [P in keyof T]: T[P] };Generated:
// Note: Mapped types are handled as their resolved types
// The generator will use the actual resolved interface structure
export const isPartial = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<Partial<T>> => typeGuardT; // Simplified - actual implementation depends on T14. Template Literal Types
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
export type ApiEndpoint = `/api/${string}`;
export type UserId = `user_${string}`;Generated:
export const isHttpMethod = isOneOf('GET', 'POST', 'PUT', 'DELETE');
export const isApiEndpoint = isString; // Template literals are validated as strings
export const isUserId = isString; // Template literals are validated as strings15. Utility Types
export type Pick<T, K extends keyof T> = { [P in K]: T[P] };
export type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
export type Record<K extends keyof any, T> = { [P in K]: T };Generated:
// Note: Utility types are handled as their resolved types
// The generator will use the actual resolved interface structure
export const isPick = <T, K extends keyof T>(
typeGuardT: TypeGuardFn<T>,
keys: K[],
): TypeGuardFn<Pick<T, K>> => typeGuardT; // Simplified
export const isOmit = <T, K extends keyof any>(
typeGuardT: TypeGuardFn<T>,
keys: K[],
): TypeGuardFn<Omit<T, K>> => typeGuardT; // Simplified
export const isRecord = <K extends keyof any, T>(
keyGuard: TypeGuardFn<K>,
valueGuard: TypeGuardFn<T>,
): TypeGuardFn<Record<K, T>> => isObjectWithEachItem(valueGuard);16. Function Types
export type EventHandler = (event: Event) => void;
export type AsyncFunction<T> = () => Promise<T>;
export type Callback<T> = (data: T) => void;Generated:
export const isEventHandler = isFunction;
export const isAsyncFunction = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<AsyncFunction<T>> => isFunction; // Simplified - function types are validated as functions
export const isCallback = <T>(
typeGuardT: TypeGuardFn<T>,
): TypeGuardFn<Callback<T>> => isFunction; // Simplified - function types are validated as functions17. Class Types
export class User {
constructor(
public id: number,
public name: string,
) {
}
}
export interface UserInstance extends User {
email: string;
}Generated:
export const isUser = isInstanceOf(User);
export const isUserInstance = isExtensionOf(
isUser,
isType<Omit<UserInstance, keyof User>>({
email: isString,
}),
);18. Branded Types
export type UserId = string & { readonly brand: unique symbol };
export type Email = string & { readonly brand: unique symbol };
export type Age = number & { readonly brand: unique symbol };Generated:
export const isUserId = isString; // Branded types are validated as their base type
export const isEmail = isString; // Branded types are validated as their base type
export const isAge = isNumber; // Branded types are validated as their base type19. Const Assertions
export const STATUS = ['active', 'inactive', 'pending'] as const;
export type Status = (typeof STATUS)[number];
export const CONFIG = {
api: 'https://api.example.com',
timeout: 5000,
} as const;
export type Config = typeof CONFIG;Generated:
export const isStatus = isOneOf('active', 'inactive', 'pending');
export const isConfig = isType<Config>({
api: isString,
timeout: isNumber,
});20. Complex Nested Types
export interface ComplexUser {
id: number;
profile: {
name: string;
avatar?: string;
preferences: {
theme: 'light' | 'dark';
notifications: boolean;
};
};
posts: Array<{
id: string;
title: string;
content: string;
tags: string[];
published: boolean;
}>;
metadata: Record<string, unknown>;
}Generated:
export const isComplexUser: TypeGuardFn<ComplexUser> = isType<ComplexUser>({
id: isNumber,
profile: isType<{
name: string;
avatar?: string;
preferences: {
theme: 'light' | 'dark';
notifications: boolean;
};
}>({
name: isString,
avatar: isUndefinedOr(isString),
preferences: isType<{
theme: 'light' | 'dark';
notifications: boolean;
}>({
theme: isOneOf('light', 'dark'),
notifications: isBoolean,
}),
}),
posts: isArrayWithEachItem(
isType<{
id: string;
title: string;
content: string;
tags: string[];
published: boolean;
}>({
id: isString,
title: isString,
content: isString,
tags: isArrayWithEachItem(isString),
published: isBoolean,
}),
),
metadata: isObjectWithEachItem(isUnknown),
});Advanced Capabilities
- Automatic Post-Processing: Optionally runs Prettier, ESLint, and TypeScript checks on generated files.
- Cycle Detection: Detects and handles recursive and cyclic type references.
- Custom Type Guards: Generate custom guards for any TypeScript type node.
- AST Utilities: Exposes utilities for advanced users (e.g., property extraction, recursion detection).
- Import Path Consistency: Maintains your project's import structure and path aliases.
- External Package Support: Properly handles types from npm packages with smart fallback logic.
Complete Feature Support
Guardz Generator supports all major TypeScript features:
✅ Basic Types
- Primitive Types:
string,number,boolean,bigint,symbol - Nullable Types:
string | null,number | undefined, etc. - Optional Properties:
name?: string - Arrays:
string[],number[],Array<T> - Tuples:
[string, number],[number, number, number]
✅ Complex Types
- Union Types:
'active' | 'inactive' | 'pending' - Intersection Types:
HasId & HasTimestamps - Generic Types:
ApiResponse<T>,PaginatedResponse<T> - Recursive Types: Self-referencing interfaces and types
- Index Signatures:
{ [key: string]: unknown }
✅ Interface Features
- Basic Interfaces: Simple property definitions
- Interface Extensions:
interface B extends Awith proper inheritance - Multi-level Inheritance:
A extends B extends C - Generic Interfaces:
interface Container<T> - Interface Merging: Multiple interface declarations
✅ Type Aliases
- Basic Type Aliases:
type UserId = string - Union Type Aliases:
type Status = 'active' | 'inactive' - Generic Type Aliases:
type Result<T> = Success<T> | Error - Mapped Types:
type Partial<T> = { [P in keyof T]?: T[P] } - Conditional Types:
type NonNullable<T> = T extends null | undefined ? never : T - Template Literal Types:
type UserId =user_${string}`` - Branded Types:
type UserId = string & { readonly brand: unique symbol } - Const Assertions:
type Status = typeof STATUS[number]
✅ Advanced Features
- Enums: Both string and numeric enums
- BigInt Support:
biginttype and operations - Advanced Number Types:
PositiveInteger,NonNegativeInteger, etc. - Cross-file References: Types imported from other files
- NPM Package Types: Types from external packages
- Path Aliases:
@/types/User→@/types/User.guardz - Index Signatures:
{ [key: string]: string } - Function Types:
(event: Event) => void - Class Types:
class UserwithisInstanceOf - Utility Types:
Pick,Omit,Record, etc. - Complex Nested Types: Deep object structures with arrays and unions
✅ Import Handling
- Relative Imports:
'./models/User'→'./models/User.guardz' - Path Aliases:
'@/types/ApiResponse'→'@/types/ApiResponse.guardz' - Global Imports:
'@/global/_GlobalTypes'→'@/global/isTypeName.guardz' - NPM Packages:
'axios'→isAsserted<AxiosResponse> - Smart Fallbacks: Uses local guards when available, falls back to
isAsserted
✅ Code Quality
- Prettier Formatting: Consistent code style
- ESLint Integration: Lint generated files
- TypeScript Checking: Verify generated code compiles
- Error Handling: Graceful handling of unsupported types
- Performance: Efficient AST traversal and code generation
Configuration
Create a guardz.config.ts file in your project root:
export default {
includes: ['src/**/*.ts'],
excludes: ['node_modules/**/*', '**/*.test.ts', '**/*.guardz.ts'],
output: './generated',
postProcess: true,
};Why Use Guardz Generator?
- Save Time: No more hand-writing repetitive type guards.
- Increase Safety: Get runtime validation for your TypeScript types.
- Stay Up-to-date: Supports the latest TypeScript and guardz 1.9.0 features including new Web API guards.
- Flexible: Use in any project, with CLI or API.
- Consistent: Maintains your project's import structure and conventions.
- Comprehensive: Handles all TypeScript features including generics, unions, intersections, and interface extensions.
Support This Project
If you find Guardz Generator helpful, please consider supporting its development! Your sponsorship helps maintain and improve this open-source project.
GitHub Sponsors
Sponsorship Tiers
$5/month - Supporter 🎉
- Get your name listed as a supporter
- Early access to new features
- Priority issue responses
$20/month - Coffee + Shout-out ☕
- All Supporter benefits
- Monthly shout-out on social media
- Direct access to development roadmap
$100/month - Company Sponsor 🏢
- All previous benefits
- Company logo featured in README
- Dedicated support channel
- Custom feature requests
$500+/month - Integration/Consulting Call 💼
- All previous benefits
- Monthly 1-hour consulting call
- Custom integration support
- White-label solutions
- Enterprise deployment assistance
Other Ways to Support
- ⭐ Star the repository if you find it useful
- 🐛 Report bugs and suggest improvements
- 📝 Contribute code via pull requests
- 📢 Share with your network
License
MIT