typescriptintermediate
Schema Validation with Zod-like Patterns
Build a minimal schema validation library inspired by Zod using TypeScript type inference.
typescriptPress ⌘/Ctrl + Shift + C to copy
// Minimal Zod-like validator
type Infer<T> = T extends Validator<infer U> ? U : never;
class Validator<T> {
constructor(private parse: (input: unknown) => T) {}
validate(input: unknown): { success: true; data: T } | { success: false; error: string } {
try {
return { success: true, data: this.parse(input) };
} catch (e: any) {
return { success: false, error: e.message };
}
}
optional(): Validator<T | undefined> {
return new Validator((input) => {
if (input === undefined) return undefined;
return this.parse(input);
});
}
}
const v = {
string: () => new Validator<string>((input) => {
if (typeof input !== 'string') throw new Error(`Expected string, got ${typeof input}`);
return input;
}),
number: () => new Validator<number>((input) => {
if (typeof input !== 'number' || isNaN(input as number))
throw new Error(`Expected number, got ${typeof input}`);
return input as number;
}),
boolean: () => new Validator<boolean>((input) => {
if (typeof input !== 'boolean') throw new Error(`Expected boolean`);
return input;
}),
object: <S extends Record<string, Validator<any>>>(shape: S) => {
type Shape = { [K in keyof S]: Infer<S[K]> };
return new Validator<Shape>((input) => {
if (typeof input !== 'object' || input === null) throw new Error('Expected object');
const result = {} as any;
for (const [key, validator] of Object.entries(shape)) {
const val = (input as any)[key];
result[key] = (validator as any).parse(val);
}
return result;
});
},
array: <T>(itemValidator: Validator<T>) => new Validator<T[]>((input) => {
if (!Array.isArray(input)) throw new Error('Expected array');
return input.map((item, i) => {
try { return (itemValidator as any).parse(item); }
catch (e: any) { throw new Error(`[${i}]: ${e.message}`); }
});
}),
};
// Usage
const UserSchema = v.object({
name: v.string(),
age: v.number(),
email: v.string(),
active: v.boolean().optional(),
});
type User = Infer<typeof UserSchema>;
console.log(UserSchema.validate({ name: 'Alice', age: 30, email: 'a@b.com' }));
console.log(UserSchema.validate({ name: 123, age: 'bad' }));Use Cases
- API request validation
- Configuration parsing
- Form input validation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
Request Validation Schema Builder
Build a lightweight request validation layer with type inference for API endpoints.
Best for: API request body validation
#nodejs#validation
typescriptbeginner
Environment Variable Validator
Validates required environment variables at startup and returns a typed config object or throws with missing keys.
Best for: App startup validation
#config#validation
typescriptintermediate
TypeScript Typed Event Emitter
Create type-safe event emitters in Node.js with full TypeScript support and autocomplete.
Best for: Type-safe pub/sub communication between modules
#nodejs#events
typescriptbeginner
Custom Error Classes
Create typed custom error classes with HTTP status codes, error codes, and structured error handling.
Best for: Structured API error responses
#nodejs#error