type-compiler
Version:
A TypeScript compiler plugin for enhanced runtime type checking and analysis with Zod validation
151 lines (131 loc) • 4.63 kB
text/typescript
/**
* Example of custom error messages with type-compiler
*
* This example demonstrates how to configure and use custom error messages
* with different validation rules and how they appear in runtime errors.
*/
import { z } from 'zod';
// These interfaces will have their Zod schemas generated by type-compiler
// The validation rules and custom error messages are defined in tsconfig.json
interface User {
id: string;
name: string;
email: string; // Will use custom error message for email format
role: string; // Will use custom error message for allowed roles
age: number; // Will use custom error message for age range
}
interface Product {
id: string;
name: string;
price: number; // Will use custom error message for minimum price
inventory: number; // Will use custom error message for non-negative inventory
}
// This would be generated by type-compiler at build time
// Included here to demonstrate expected output
// Using proper Zod method chaining - setErrorMap is typically what Zod uses
// for custom error messages rather than a .message() method
const zUser = z.object({
id: z.string().uuid().describe("ID must be a valid UUID"),
name: z.string().min(2).describe("Name must be at least 2 characters"),
email: z.string().email().describe("Company email must end with @company.com"),
role: z.enum(['admin', 'user', 'guest']).describe("Role must be one of: admin, user, or guest"),
age: z.number().int().min(18).max(120).describe("Age must be between 18 and 120")
});
const zProduct = z.object({
id: z.string().uuid().describe("ID must be a valid UUID"),
name: z.string().min(1),
price: z.number().positive().min(0.01).describe("Price must be greater than $0.01"),
inventory: z.number().int().min(0).describe("Inventory must be a non-negative integer")
});
// Custom error formatting function that uses the descriptions as error messages
const customErrorMap: z.ZodErrorMap = (issue, ctx) => {
// If we have a custom description, use it as the error message
if (ctx.data?.description) {
return { message: ctx.data.description };
}
// Otherwise fall back to default error message
return { message: ctx.defaultError };
};
// Set the custom error map
z.setErrorMap(customErrorMap);
/**
* Validates user data with helpful error messages
*/
function validateUser(userData: unknown): User {
try {
return zUser.parse(userData);
} catch (error) {
if (error instanceof z.ZodError) {
console.error("Validation failed with custom error messages:");
error.errors.forEach(err => {
console.error(`- ${err.path.join('.')}: ${err.message}`);
});
}
throw error;
}
}
/**
* Validates product data with helpful error messages
*/
function validateProduct(productData: unknown): Product {
try {
return zProduct.parse(productData);
} catch (error) {
if (error instanceof z.ZodError) {
console.error("Validation failed with custom error messages:");
error.errors.forEach(err => {
console.error(`- ${err.path.join('.')}: ${err.message}`);
});
}
throw error;
}
}
// Example usage
function main() {
console.log("=== Custom Error Messages Example ===\n");
// Valid user example
try {
const validUserData = {
id: "123e4567-e89b-12d3-a456-426614174000",
name: "Jane Smith",
email: "jane@company.com",
role: "admin" as const,
age: 35
};
const validUser = validateUser(validUserData);
console.log("Valid user:", validUser);
} catch (error) {
// This shouldn't execute for valid data
}
console.log("\n=== Invalid User Example ===\n");
// Invalid user example
try {
const invalidUserData = {
id: "invalid-uuid",
name: "J",
email: "jane@gmail.com", // Not a company email
role: "manager", // Not in allowed roles
age: 16 // Below minimum age
};
validateUser(invalidUserData);
} catch (error) {
// The validation should fail with helpful custom messages
console.log("Expected validation failure with custom messages\n");
}
console.log("\n=== Invalid Product Example ===\n");
// Invalid product example
try {
const invalidProductData = {
id: "123",
name: "Laptop",
price: 0, // Zero price
inventory: -5 // Negative inventory
};
validateProduct(invalidProductData);
} catch (error) {
// The validation should fail with helpful custom messages
console.log("Expected validation failure with custom messages\n");
}
}
// Run the example
main();