Lightweight and extensible schema validation library for TypeScript/JavaScript
Full TypeScript support with complete type inference and safety.
Validate against databases, APIs, and external services seamlessly.
String, Number, Object, Array, Date, Email, Base64, File and more.
Validate and transform data in one step with chaining API.
Get all validation errors at once for better UX.
Lightweight with only date-fns for date operations.
Install Katax Core via npm, yarn, or pnpm:
npm install katax-core import { k } from 'katax-core';
const userSchema = k.object({
name: k.string().minLength(2),
email: k.string().email(),
age: k.number().min(18).max(100),
tags: k.array(k.string()).optional()
});
const result = userSchema.safeParse({
name: 'John Doe',
email: 'john@example.com',
age: 25,
tags: ['developer', 'typescript']
});
if (result.success) {
console.log('Valid data:', result.data);
} else {
console.log('Errors:', result.issues);
} import { k } from 'katax-core';
// Async validator to check if email already exists
const emailUniqueValidator = async (email, path) => {
const exists = await db.users.findOne({ email });
if (exists) {
return [{ path, message: 'Email already registered' }];
}
return [];
};
const registrationSchema = k.object({
email: k.email().asyncRefine(emailUniqueValidator),
password: k.string()
.minLength(8)
.regex(/[A-Z]/, 'Must contain uppercase')
.regex(/[0-9]/, 'Must contain number')
});
// Use async validation
const result = await registrationSchema.safeParseAsync({
email: 'user@example.com',
password: 'SecurePass123'
});
if (result.success) {
console.log('Valid data:', result.data);
} import { k, kataxInfer } from 'katax-core';
const createProjectSchema = k.object({
title: k.string().minLength(3),
description: k.string().optional(),
tags: k.array(k.string()),
isPublic: k.boolean().default(true)
});
// Automatically infer TypeScript type
export type CreateProjectData = kataxInfer<typeof createProjectSchema>;
// Type: { title: string; description?: string; tags: string[]; isPublic: boolean }
function createProject(data: CreateProjectData) {
// Full type safety and autocomplete
console.log(data.title); // ✓ string
console.log(data.tags); // ✓ string[]
} import { k } from 'katax-core';
const blogSchema = k.object({
title: k.string().minLength(5).maxLength(100),
slug: k.string().regex(/^[a-z0-9-]+$/),
author: k.object({
name: k.string(),
email: k.email(),
bio: k.string().optional()
}),
tags: k.array(k.string()).unique().minLength(1),
publishedAt: k.date().isPast(),
metadata: k.object({
views: k.number().min(0).default(0),
likes: k.number().min(0).default(0)
}).optional()
});
const result = blogSchema.safeParse({
title: 'Introduction to Katax Core',
slug: 'intro-to-katax',
author: {
name: 'Vinicio Esparza',
email: 'vinicio@example.com'
},
tags: ['typescript', 'validation'],
publishedAt: new Date('2024-01-01')
}); k.string()
.minLength(3)
.maxLength(50)
.email()
.url()
.regex(/^[a-zA-Z]+$/) k.number()
.min(0)
.max(100)
.positive()
.integer() k.date()
.min('2024-01-01')
.max('2024-12-31')
.isFuture()
.isPast() k.email()
.domain('company.com')
.corporate()
.noPlus() k.array(k.string())
.minLength(1)
.maxLength(10)
.unique() k.file()
.image()
.maxSize(5 * 1024 * 1024)
.extensions(['.jpg'])