Files
gh-jezweb-claude-skills-ski…/references/validation-libraries.md
2025-11-30 08:24:59 +08:00

6.9 KiB

Validation Libraries Comparison

Comprehensive comparison of validation libraries for Hono: Zod, Valibot, Typia, and ArkType.

Last Updated: 2025-10-22


Quick Comparison

Feature Zod Valibot Typia ArkType
Bundle Size ~57KB ~1-5KB ~0KB ~15KB
Performance Good Excellent Best Excellent
Type Safety Excellent Excellent Best Excellent
Ecosystem Largest Growing Small Growing
Learning Curve Easy Easy Medium Easy
Compilation Runtime Runtime AOT Runtime
Tree Shaking Limited Excellent N/A Good

Zod

Install: npm install zod @hono/zod-validator

Pros:

  • Most popular (11M+ weekly downloads)
  • Extensive ecosystem and community
  • Excellent TypeScript support
  • Rich feature set (transforms, refinements, etc.)
  • Great documentation

Cons:

  • Larger bundle size (~57KB)
  • Slower performance vs alternatives
  • Limited tree-shaking

Best for:

  • Production applications with complex validation needs
  • Projects prioritizing ecosystem and community support
  • Teams familiar with Zod

Example:

import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const schema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(18).optional(),
})

app.post('/users', zValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})

Valibot

Install: npm install valibot @hono/valibot-validator

Pros:

  • Tiny bundle size (1-5KB with tree-shaking)
  • Excellent performance
  • Modular design (import only what you need)
  • Similar API to Zod
  • Great TypeScript support

Cons:

  • Smaller ecosystem vs Zod
  • Newer library (less battle-tested)
  • Fewer integrations

Best for:

  • Applications prioritizing bundle size
  • Performance-critical applications
  • Projects that want Zod-like API with better performance

Example:

import { vValidator } from '@hono/valibot-validator'
import * as v from 'valibot'

const schema = v.object({
  name: v.pipe(v.string(), v.minLength(1), v.maxLength(100)),
  email: v.pipe(v.string(), v.email()),
  age: v.optional(v.pipe(v.number(), v.integer(), v.minValue(18))),
})

app.post('/users', vValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})

Typia

Install: npm install typia @hono/typia-validator

Pros:

  • Fastest validation (AOT compilation)
  • Zero runtime overhead
  • No bundle size impact
  • Uses TypeScript types directly
  • Compile-time validation

Cons:

  • Requires build step (TypeScript transformer)
  • More complex setup
  • Smaller community
  • Limited to TypeScript

Best for:

  • Maximum performance requirements
  • Applications with strict bundle size constraints
  • Projects already using TypeScript transformers

Example:

import { typiaValidator } from '@hono/typia-validator'
import typia from 'typia'

interface User {
  name: string
  email: string
  age?: number
}

const validate = typia.createValidate<User>()

app.post('/users', typiaValidator('json', validate), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})

ArkType

Install: npm install arktype @hono/arktype-validator

Pros:

  • Excellent performance (1.5x faster than Zod)
  • Intuitive string-based syntax
  • Great error messages
  • TypeScript-first
  • Small bundle size (~15KB)

Cons:

  • Newer library
  • Smaller ecosystem
  • Different syntax (learning curve)

Best for:

  • Developers who prefer string-based schemas
  • Performance-conscious projects
  • Projects that value developer experience

Example:

import { arktypeValidator } from '@hono/arktype-validator'
import { type } from 'arktype'

const schema = type({
  name: 'string',
  email: 'email',
  'age?': 'number>=18',
})

app.post('/users', arktypeValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})

Performance Benchmarks

Based on community benchmarks (approximate):

Typia:    ~10,000,000 validations/sec  (Fastest - AOT)
Valibot:  ~5,000,000 validations/sec
ArkType:  ~3,500,000 validations/sec
Zod:      ~2,300,000 validations/sec

Note: Actual performance varies by schema complexity and runtime.


Bundle Size Comparison

Typia:   0 KB    (AOT compilation)
Valibot: 1-5 KB  (with tree-shaking)
ArkType: ~15 KB
Zod:     ~57 KB

Feature Comparison

Transformations

Library Support Example
Zod z.string().transform(Number)
Valibot v.pipe(v.string(), v.transform(Number))
Typia Built into types
ArkType Type inference

Refinements

Library Support Example
Zod z.string().refine((val) => val.length > 0)
Valibot v.pipe(v.string(), v.check((val) => val.length > 0))
Typia Custom validators
ArkType Narrow types

Default Values

Library Support Example
Zod z.string().default('default')
Valibot v.optional(v.string(), 'default')
Typia ⚠️ Limited
ArkType Type defaults

Recommendations

Choose Zod if:

  • You want the largest ecosystem and community
  • You need extensive documentation and examples
  • Bundle size is not a primary concern
  • You want battle-tested reliability

Choose Valibot if:

  • Bundle size is critical
  • You want Zod-like API with better performance
  • You're building a modern application with tree-shaking
  • You want modular imports

Choose Typia if:

  • Performance is absolutely critical
  • You can afford a more complex build setup
  • Zero runtime overhead is required
  • You're already using TypeScript transformers

Choose ArkType if:

  • You prefer string-based schema syntax
  • You want excellent error messages
  • Performance is important but not critical
  • You value developer experience

Migration Guide

Zod → Valibot

// Zod
const schema = z.object({
  name: z.string().min(1),
  age: z.number().optional(),
})

// Valibot
const schema = v.object({
  name: v.pipe(v.string(), v.minLength(1)),
  age: v.optional(v.number()),
})

Zod → ArkType

// Zod
const schema = z.object({
  name: z.string().min(1),
  age: z.number().optional(),
})

// ArkType
const schema = type({
  name: 'string>0',
  'age?': 'number',
})

Official Documentation