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
A TypeScript type guard generator that uses the guardz library (v1.0.6) to generate runtime type checking functions from TypeScript interfaces and type aliases.
Features
- Functional Architecture: Built with functional programming principles for better maintainability and testability
- Modular Design: Separated concerns into focused modules (AST utils, type detection, generators, etc.)
- Type Safety: Full TypeScript support with proper type definitions
- Generic Support: Handles generic interfaces and type aliases
- Advanced Recursion Support: Detects both direct and indirect recursive types with sophisticated cycle detection
- Enhanced Enum Handling: Uses
isEnum(EnumName)format for cleaner enum type guards - Union Types: Generates guards for union types including null/undefined handling
- Cross-file References: Resolves types across multiple files
- Prettier Integration: Automatically formats generated code
Installation
npm install guardz-generatorUsage
CLI
Generate type guards for all exported interfaces and type aliases:
npx guardz-generator generate "src/**/*.ts"Generate a type guard for a specific type:
npx guardz-generator generate "src/**/*.ts" -t UserDTOProgrammatic API
import { TypeGuardGenerator } from 'guardz-generator';
const generator = new TypeGuardGenerator(['src/**/*.ts']);
// Generate all type guards
const files = generator.generateAllTypeGuards();
await generator.writeTypeGuardsToSameDirectory(files);
// Generate a specific type guard
const typeGuardCode = generator.generateTypeGuard('UserDTO');Architecture
The project follows functional programming principles with clear separation of concerns:
Core Modules
src/types.ts: Type definitions and interfacessrc/core/type-guard-generator.ts: Main orchestrator classsrc/generators/: Type guard generation logictype-guard-generators.ts: Handles different TypeScript node typesinterface-generators.ts: Interface-specific generationtype-alias-generators.ts: Type alias generationfile-generators.ts: File generation utilities
src/utils/: Pure utility functionsast-utils.ts: AST manipulation utilities including cycle detectiontype-detection.ts: Type detection and validationimport-collectors.ts: Import statement generation
Functional Principles
- Pure Functions: Most functions are pure and side-effect free
- Composition: Complex operations are built from smaller, focused functions
- Immutability: Data structures are treated as immutable
- Separation of Concerns: Each module has a single responsibility
- Testability: Functions are easily testable in isolation
Supported TypeScript Features
New in v1.0.6 - Latest guardz Features
The generator now supports all the latest guardz 1.0.6 features:
Advanced Number Types
export interface User {
id: PositiveInteger; // > 0 and whole number
age: NonNegativeInteger; // ≥ 0 and whole number
score: Integer; // whole number
temperature: NegativeNumber; // < 0
}
// Generates:
export const isUser = isType<User>({
id: isPositiveInteger,
age: isNonNegativeInteger,
score: isInteger,
temperature: isNegativeNumber,
});BigInt Support
export interface LargeData {
bigId: bigint;
timestamp: bigint;
}
// Generates:
export const isLargeData = isType<LargeData>({
bigId: isBigInt,
timestamp: isBigInt,
});Enhanced Nullable/Optional Types
export interface Config {
name: string | null | undefined; // Uses isNilOr
email?: string | null; // Uses isUndefinedOr
}
// Generates:
export const isConfig = isType<Config>({
name: isNilOr(isString),
email: isUndefinedOr(isNullOr(isString)),
});Tuple Types
export interface Coordinates {
point: [number, number];
data: [string, number, boolean];
}
// Generates:
export const isCoordinates = isType<Coordinates>({
point: isTuple([isNumber, isNumber]),
data: isTuple([isString, isNumber, isBoolean]),
});Composite Types
export interface Person {
name: string;
age: number;
}
export interface Employee extends Person {
employeeId: string;
department: string;
}
// Generates:
export const isPerson = isType<Person>({ name: isString, age: isNumber });
export const isEmployee = isExtensionOf(isPerson, isType<Employee>({
employeeId: isString,
department: isString,
}));Interfaces
export interface User {
id: number;
name: string;
email?: string;
profile: UserProfile;
}
// Generates:
export const isUser = isType<User>({
id: isNumber,
name: isString,
email: isUndefinedOr(isString),
profile: isUserProfile,
});Generic Interfaces
export interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// Generates:
export const isApiResponse = <T>(typeGuardT: TypeGuardFn<T>): TypeGuardFn<ApiResponse<T>> =>
isType<ApiResponse<T>>({
data: typeGuardT,
status: isNumber,
message: isString,
});Enums
export enum UserStatus {
ACTIVE = 'active',
INACTIVE = 'inactive',
PENDING = 'pending',
}
export interface User {
id: number;
status: UserStatus;
}
// Generates:
import { UserStatus } from './types';
export const isUser = isType<User>({
id: isNumber,
status: isEnum(UserStatus),
});Type Aliases
export type UserRole = 'admin' | 'user' | 'guest';
// Generates:
export const isUserRole = isOneOf('admin', 'user', 'guest');Union Types
export interface User {
id: number;
name: string | null;
role: 'admin' | 'user' | 'guest';
}
// Generates:
export const isUser = isType<User>({
id: isNumber,
name: isNullOr(isString),
role: isOneOf('admin', 'user', 'guest'),
});Direct Recursive Types
export interface TreeNode {
value: number;
children: TreeNode[];
}
// Generates:
export function isTreeNode(value: unknown): value is TreeNode {
return isType<TreeNode>({
value: isNumber,
children: isArrayWithEachItem(isTreeNode),
})(value);
}Indirect Recursive Types
// Type A references Type B, Type B references Type A
export interface NodeA {
id: number;
nodeB: NodeB;
}
export interface NodeB {
id: number;
nodeA: NodeA;
}
// Generates function format for both types:
export function isNodeA(value: unknown): value is NodeA {
return isType<NodeA>({
id: isNumber,
nodeB: isNodeB,
})(value);
}
export function isNodeB(value: unknown): value is NodeB {
return isType<NodeB>({
id: isNumber,
nodeA: isNodeA,
})(value);
}Advanced Features
Sophisticated Cycle Detection
The generator uses a dependency graph with depth-first search to detect complex recursive patterns:
- Direct recursion:
TreeNodecontainsTreeNode[] - Indirect recursion:
NodeA→NodeB→NodeA - Multi-way cycles:
Alpha→Beta→Gamma→Alpha
All recursive types automatically use function format to handle circular references properly.
Enhanced Enum Support
Enums are detected automatically and use the isEnum() function:
// Instead of generating separate isUserStatus.guardz.ts file:
export const isUserStatus = isEnum(UserStatus);
// Direct enum import and usage:
import { UserStatus } from './types';
status: isEnum(UserStatus)Advanced Usage
Custom Type Guards
import { convertTypeToGuard } from 'guardz-generator';
const typeNode = // ... TypeScript AST node
const guardCode = convertTypeToGuard(typeNode, { sourceFiles });AST Utilities
import {
extractProperties,
isRecursiveType,
isRecursiveOrCyclic,
buildTypeDependendencyGraph,
detectCycles
} from 'guardz-generator';
// Check for direct recursion
const isRecursive = isRecursiveType(interfaceDecl);
// Check for both direct and indirect recursion
const isCyclic = isRecursiveOrCyclic(interfaceDecl, allInterfaces);
// Build dependency graph for analysis
const graph = buildTypeDependendencyGraph(interfaces);
const cyclicTypes = detectCycles(graph);Type Detection
import { isEnumType, isInterfaceType } from 'guardz-generator';
const isEnum = isEnumType('UserRole', sourceFiles);
const isInterface = isInterfaceType('User', sourceFiles);Configuration
The generator uses TypeScript compiler options optimized for type guard generation:
{
target: ts.ScriptTarget.ES2020,
module: ts.ModuleKind.CommonJS,
strict: true,
esModuleInterop: true,
skipLibCheck: true,
}Contributing
The project follows functional programming principles:
- Pure Functions: Keep functions pure and side-effect free
- Small Functions: Break complex operations into smaller, focused functions
- Type Safety: Use TypeScript types extensively
- Composition: Build complex operations from simpler ones
- Testing: Write tests for individual functions
License
MIT