Property Validator
Runtime type validation with TypeScript inference and high performance.
Overview
Property Validator provides schema-based runtime type validation with full TypeScript type inference and elite performance. Beats Zod 2-72x in all categories, matches Valibot on primitives while dominating objects/arrays, and competes with TypeBox JIT.
Status: Production Ready (v0.10.0)
Language: TypeScript
Tests: 898 tests passing
Bundle Size: 30KB minified, 8KB gzipped
Repository: tuulbelt/property-validator
Features
Tree-Shakeable Imports (v0.9.0)
Import only what you need with named exports:
// Named exports - tree-shakeable
import { string, number, object, validate } from '@tuulbelt/property-validator';
// Fluent API - v namespace (also from main entry)
import { v, validate } from '@tuulbelt/property-validator';
Three API Tiers (v0.8.5)
Choose your speed vs. detail trade-off:
| API | Speed | Returns | Use Case |
|---|---|---|---|
validate() | ~170 ns | Result with errors | Forms, APIs, debugging |
check() | ~60 ns | Boolean only | Filtering, conditionals |
compileCheck() | ~55 ns | Pre-compiled boolean | Hot paths, pipelines |
Built-in Validators (v0.8.5)
Common validation patterns included:
// String validators
v.string().email() // RFC 5322 email
v.string().url() // HTTP/HTTPS URL
v.string().uuid() // UUID v1-v5
v.string().min(3).max(100)
// Number validators
v.number().int() // Integer only
v.number().positive() // > 0
v.number().range(0, 100)
Schema-Based Validation
Define schemas once, get both runtime validation and TypeScript types automatically.
Clear Error Messages
Validation errors include exact paths to invalid fields, expected vs actual types, and helpful context.
Zero Runtime Dependencies
Uses only Node.js built-ins. No npm install required in production.
Performance
Property Validator v0.10.0 delivers elite performance with JIT-style optimizations.
External Comparison Results (v0.10.0)
| Category | propval | Zod | Valibot | TypeBox JIT |
|---|---|---|---|---|
| Primitives | 62 ns | 123 ns | 59 ns | 61 ns |
| Simple Objects | 56 ns | 742 ns | 169 ns | 57 ns |
| Complex Nested | 58 ns | 4.21 µs | 584 ns | 56 ns |
| Unions | 56 ns | 426 ns | 123 ns | 57 ns |
| Arrays (100) | 145 ns | 4.85 µs | 1.10 µs | 108 ns |
Summary
- vs Zod: 2.0x - 72x faster ✅ (all categories)
- vs Valibot: 2.2x - 10x faster on objects/arrays, ~tie on primitives
- vs TypeBox JIT: Competitive (~tie overall, TypeBox uses
new Function()JIT)
API Performance Comparison
| Scenario | validate() | check() | compileCheck() |
|---|---|---|---|
| Simple Object | 170 ns | 58 ns | 55 ns |
| Complex Nested | 190 ns | 60 ns | 58 ns |
| Union (3 types) | 90 ns | 66 ns | 56 ns |
| Invalid Data | 357 ns | 55 ns | 55 ns |
Key insight: check() is 6x faster for invalid data (skips error path entirely).
Quick Start
# Clone the repository
git clone https://github.com/tuulbelt/property-validator.git
cd property-validator
npm installBasic Usage
import { object, string, number, validate } from '@tuulbelt/property-validator';
const UserSchema = object({
name: string().min(1),
age: number().positive(),
email: string().email()
});
const result = validate(UserSchema, unknownData);
if (result.ok) {
console.log(result.value); // TypeScript knows the exact type
} else {
console.error(result.error.message);
}Fast Boolean Check
import { check, object, string } from '@tuulbelt/property-validator';
const UserSchema = object({ name: string() });
// Fast pass/fail - no error details
if (check(UserSchema, data)) {
processUser(data);
}
// Filter arrays efficiently
const validUsers = users.filter(u => check(UserSchema, u));Pre-compiled for Hot Paths
import { compileCheck, object, number } from '@tuulbelt/property-validator';
const PointSchema = object({ x: number(), y: number() });
const isValidPoint = compileCheck(PointSchema); // Compile once
// Use in hot loops
for (const point of points) {
if (isValidPoint(point)) {
render(point);
}
}Use Cases
- API Response Validation: Verify external API data matches expected schemas
- User Input Validation: Validate form data, CLI arguments, or configuration files
- High-Throughput Pipelines: Use
check()orcompileCheck()for data filtering - Component Props: Validate props at runtime in any framework (React, Vue, etc.)
Demo
See the tool in action:

▶ View interactive recording on asciinema.org
What's New
v0.10.0 - Full Modularization + JSON Schema
- JSON Schema Export —
toJsonSchema()converts schemas to JSON Schema Draft 7 - Full Modularization — Validators extracted to individual modules (index.ts: 3744→149 lines)
record()validator — Dynamic keys withv.record(keyValidator, valueValidator)discriminatedUnion()— Efficient tagged unions with O(1) discriminator lookupstrict()/passthrough()— Control unknown property handling on objects- Extended Validators —
cuid(),cuid2(),ulid(),nanoid(),base64(),hex(),jwt(),port(),latitude(),longitude(),percentage() - Array JIT for Objects — Optimized array-of-object validation
- 898 tests — Comprehensive test coverage
v0.9.2 - Performance-First Architecture
vnamespace available from main entry:import { v } from '@tuulbelt/property-validator'- Named exports for tree-shakeable refinements:
import { email, int } from '@tuulbelt/property-validator' /typesentry point for zero-runtime type imports- JIT compilation at schema definition time for sub-100ns validation
- Documented design philosophy: speed over bundle size
v0.9.1 - Functional Refinement API
- Tree-shakeable refinement functions:
email(),int(),positive(), etc. - Functional composition:
string(email(), minLength(5)) - 32 refinement exports for maximum tree-shaking
- 44 new tests, 680 total tests passing
v0.9.0 - Modularization
- Tree-shakeable named exports for all validators
- Separate types module:
@tuulbelt/property-validator/types sideEffects: falsefor bundler optimization
v0.8.5 - Three API Tiers
check()API for boolean-only validation (~3x faster)compileCheck()API for pre-compiled hot paths- Built-in string validators (email, url, uuid, pattern, etc.)
- Built-in number validators (int, positive, range, etc.)
v0.8.0 - JIT Bypass Pattern
- 5.36x faster than Valibot on complex nested objects
- 5.97x faster on arrays
- Recursive JIT bypass for nested validators
Next Steps
- Getting Started - Installation and basic usage
- CLI Usage - Command-line interface
- Library Usage - Import and use in your code
- Examples - Real-world validation scenarios
- API Reference - Complete API documentation