@cleverbrush/schema vs Zod

Zod is the industry standard for TypeScript schema validation — battle-tested, widely supported, and API-compatible with most ecosystem tooling. @cleverbrush/schema was designed with Zod as a reference point: the primitives and fluent builder style are intentionally familiar so migration is incremental.

Where they differ is in areas Zod never tackled: typed field-error selectors, runtime schema introspection, and a first-class extension system.

Key differences at a glance

Comparison table
Capability@cleverbrush/schemaZod 3/4Notes
TypeScript type inference✓✓InferType<> vs z.infer<>
Fluent / chainable API✓✓Nearly identical call sites
Immutable schemas✓✓Both return a new instance on every method
Zero runtime dependencies✓✓Both have no external deps
Bundle size (gzipped full)~15 KB~14 KB (v3) / ~6 KB (v4)Tree-shakeable — single builder entry points as small as ~4 KB
Validation speed (array of 100 objects)34 K ops/s17 K ops/s~2× faster in benchmarks
Standard Schema v1✓✓Both work with TanStack Form, T3 Env, etc.
Custom error messages✓✓Identical capability
Default values✓✓Identical: .default(value) or factory fn
Branded types✓✓Identical API
Readonly schemas✓✓Identical API
Typed field-error selectors✓✗result.getErrorsFor(u => u.field) — typos caught at compile time
Runtime schema introspection✓~.introspect() returns a typed stable descriptor tree; Zod exposes internals via ._def / ._zod.def (undocumented, unstable API)
PropertyDescriptors / metadata✓✗Per-field labels, descriptions, metadata
JSDoc comment preservation✓✗Carry JSDoc through to form labels and JSON Schema
Type-safe extension system✓limitedAdd typed methods to builders; Zod only has .refine()
extern() — Standard Schema interop✓✗Wrap any Standard Schema v1 library (incl. Zod) as a property
Per-property error inspection✓path-basedZod uses string/index paths; cleverbrush uses typed lambda selectors
Sync + async validation✓✓Identical capability
z.tuple([...])✓✓Use tuple([...])
z.record(key, value)✓✓Use record(string(), value)
z.map() / z.set()✓✓Use any().hasType(Map) / any().hasType(Set) with preprocessors or custom validators

▶ Full Zod → @cleverbrush/schema migration guide

Comparison with other validation libraries

How does @cleverbrush/schema compare to the full landscape of TypeScript validation libraries?

Comparison table
Feature@cleverbrush/schemaZodValibotArkTypeYupJoi
TypeScript type inference✓✓✓✓~✗
Immutable schemas✓✓✓✓✗✗
Zero dependencies✓✓✓✓✗✗
Runtime introspection✓~✗✓✗~
PropertyDescriptors / metadata✓✗✗✗✗~
JSDoc comment preservation✓✗✗✗✗✗
Custom error messages✓✓✓✓✓✓
Typed property-targeted errors✓path-basedpath-basedpath-basedpath-basedpath-based
Branded / opaque types✓✓✓✗✗✗
Sync + async validation✓✓✓sync only✓✓
Standard Schema v1✓✓✓✓✗✗
Type-safe extension system✓refine onlypipe-basednarrow only✗~
Generic / parameterized schemas✓✗✗✗✗✗
External schema interop (extern())✓✗✗✗✗✗
Object constructors✓✗✗✗✗✗
Built-in validators (email…)✓✓✓✓✓✓
Default values✓✓✓✓✓✓

✓ = full support, ~ = partial or undocumented, ✗ = not supported. Claims verified against each library's latest stable release as of this writing.