UNPKG

type-compiler

Version:

A TypeScript compiler plugin for enhanced runtime type checking and analysis with Zod validation

189 lines (165 loc) 6.47 kB
import { z } from 'zod'; import { User, Customer, AdminUser, SuperUser, PhysicalProduct, DigitalProduct, RegularProduct, // @ts-ignore - These schemas are generated by the type-compiler at build time zUser, // @ts-ignore - These schemas are generated by the type-compiler at build time zCustomer, // @ts-ignore - These schemas are generated by the type-compiler at build time zAdminUser, // @ts-ignore - These schemas are generated by the type-compiler at build time zSuperUser, // @ts-ignore - These schemas are generated by the type-compiler at build time zPhysicalProduct, // @ts-ignore - These schemas are generated by the type-compiler at build time zDigitalProduct, // @ts-ignore - These schemas are generated by the type-compiler at build time zRegularProduct } from './types'; /** * Helper function to validate and print the result */ function validateAndPrint<T>(schema: z.ZodType<T>, data: any, label: string): T | null { console.log(`\n--- Validating ${label} ---`); console.log('Input data:', data); try { const validatedData = schema.parse(data); console.log('✅ Validation passed'); console.log('Validated data:', validatedData); return validatedData; } catch (error) { if (error instanceof z.ZodError) { console.log('❌ Validation failed'); console.log('Errors:', error.errors.map(err => ({ path: err.path.join('.'), message: err.message }))); } else { console.log('❌ Unexpected error:', error); } return null; } } /** * Main function to demonstrate contextual validators */ function main() { console.log('======================================================'); console.log(' CONTEXTUAL VALIDATORS EXAMPLE'); console.log('======================================================'); console.log('This example demonstrates how validation rules differ'); console.log('for the same field name in different contexts (types)'); console.log('======================================================\n'); // Example 1: Compare User vs Customer email validation console.log('\n[EXAMPLE 1] Different email validation rules'); // Valid User (company email) const validUser: User = { id: '1', name: 'John Employee', email: 'john@company.com', // Must end with @company.com role: 'admin', // Must be admin, user, or guest status: 'active', // Must be active or inactive createdAt: new Date() }; // Invalid User (wrong email domain) const invalidUser = { id: '2', name: 'Jane Employee', email: 'jane@gmail.com', // Invalid (wrong domain) role: 'admin', status: 'active', createdAt: new Date() }; // Valid Customer (any email domain) const validCustomer: Customer = { id: '3', name: 'Bob Client', email: 'bob@gmail.com', // Any valid email works type: 'individual', // Must be individual or business status: 'pending', // Can be active, inactive, pending, or suspended createdAt: new Date() }; validateAndPrint(zUser, validUser, 'Valid User'); validateAndPrint(zUser, invalidUser, 'Invalid User (wrong email domain)'); validateAndPrint(zCustomer, validCustomer, 'Valid Customer'); // Example 2: Different status values for User vs Customer console.log('\n[EXAMPLE 2] Different status values'); const userWithInvalidStatus = { ...validUser, status: 'pending' // Invalid for User (only active/inactive allowed) }; const customerWithSameStatus = { ...validCustomer, status: 'pending' // Valid for Customer }; validateAndPrint(zUser, userWithInvalidStatus, 'User with "pending" status'); validateAndPrint(zCustomer, customerWithSameStatus, 'Customer with "pending" status'); // Example 3: Pattern-based type matching for Products console.log('\n[EXAMPLE 3] Pattern-based validation for Products'); const validPhysicalProduct: PhysicalProduct = { id: '4', name: 'Desk Chair', description: 'Ergonomic office chair', price: 199.99, // Must be >= 0.01 inventory: 42, // Must be integer >= 0 weight: 15.5, dimensions: { length: 24, width: 24, height: 48 }, createdAt: new Date() }; const invalidPhysicalProduct = { ...validPhysicalProduct, price: 0, // Invalid (must be >= 0.01) inventory: -5 // Invalid (must be >= 0) }; // Regular product doesn't get the stricter price validation const validRegularProduct: RegularProduct = { id: '5', name: 'Generic Item', price: 0.001, // Only needs to be positive, no minimum createdAt: new Date() }; validateAndPrint(zPhysicalProduct, validPhysicalProduct, 'Valid Physical Product'); validateAndPrint(zPhysicalProduct, invalidPhysicalProduct, 'Invalid Physical Product'); validateAndPrint(zRegularProduct, validRegularProduct, 'Valid Regular Product (less strict price validation)'); // Example 4: Pattern matching for Admin/Super users console.log('\n[EXAMPLE 4] Pattern matching for Admin/Super users'); const validAdminUser: AdminUser = { id: '6', name: 'Admin Person', email: 'admin@company.com', role: 'admin', permissions: ['read', 'write', 'delete'], // Must be non-empty array createdAt: new Date() }; const invalidAdminUser = { ...validAdminUser, permissions: [] // Invalid (must have at least one permission) }; const validSuperUser: SuperUser = { id: '7', name: 'Super Person', email: 'super@company.com', role: 'admin', permissions: ['read', 'write', 'delete', 'admin'], // Must be non-empty array createdAt: new Date() }; validateAndPrint(zAdminUser, validAdminUser, 'Valid Admin User'); validateAndPrint(zAdminUser, invalidAdminUser, 'Invalid Admin User (empty permissions)'); validateAndPrint(zSuperUser, validSuperUser, 'Valid Super User (same validation rules)'); console.log('\n======================================================'); console.log('Contextual validators enable type-specific validation'); console.log('rules even for fields with the same name.'); console.log('======================================================'); } // Run the examples main();