Skip to content

Latest commit

Β 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ›  zod-resolver-lite

A tiny, dependency-free Zod resolver for React Hook Form

npm version TypeScript License

Drop-in replacement for @hookform/resolvers/zod
when you hit import errors, bundler issues, or TypeScript headaches.

Features β€’ Installation β€’ Usage β€’ API β€’ Why This Exists


✨ Features

Feature Description
πŸͺΆ Lightweight ~50 lines of code, zero dependencies beyond peer deps
πŸ”„ Zod v4+ Ready No deprecated imports, fully compatible with latest Zod
πŸ“¦ Nested Support Handles items[0].name array paths correctly
🎯 All Errors Mode Full criteriaMode: "all" support
πŸ›‘οΈ Type Safe 100% TypeScript with full inference
⚑ Async First Built for async validation out of the box

πŸ“¦ Installation

npm install zod-resolver-lite zod react-hook-form
# or with your favorite package manager
pnpm add zod-resolver-lite zod react-hook-form
yarn add zod-resolver-lite zod react-hook-form

Peer Dependencies

Package Version
zod ^4.0.0
react-hook-form ^7.0.0

πŸš€ Usage

Basic Example

import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "zod-resolver-lite";

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});

type FormData = z.infer<typeof schema>;

export function LoginForm() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>({
    resolver: zodResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register("email")} placeholder="Email" />
      {errors.email && <span>{errors.email.message}</span>}

      <input {...register("password")} type="password" placeholder="Password" />
      {errors.password && <span>{errors.password.message}</span>}

      <button type="submit">Login</button>
    </form>
  );
}

Nested Arrays

Perfect for dynamic forms with field arrays:

const schema = z.object({
  users: z.array(
    z.object({
      name: z.string().min(2, "Name too short"),
      email: z.string().email("Invalid email"),
    })
  ),
});

// Error paths are formatted correctly:
// errors["users[0].name"]  βœ…
// errors["users[1].email"] βœ…

Criteria Mode: All Errors

Collect all validation failures for a single field:

const schema = z.object({
  password: z
    .string()
    .min(8, "At least 8 characters")
    .regex(/[A-Z]/, "Need uppercase")
    .regex(/[0-9]/, "Need a number"),
});

const { formState: { errors } } = useForm({
  resolver: zodResolver(schema),
  criteriaMode: "all", // πŸ‘ˆ Enable all errors
});

// errors.password.types = {
//   too_small: "At least 8 characters",
//   invalid_string: "Need uppercase"
// }

πŸ“– API

zodResolver(schema)

Creates a resolver function compatible with React Hook Form.

function zodResolver<T extends FieldValues>(
  schema: ZodTypeAny
): Resolver<T>
Parameter Type Description
schema ZodTypeAny Any Zod schema

Returns: A Resolver<T> function for React Hook Form


❓ Why This Exists

The Problem

Using @hookform/resolvers/zod can fail in surprising ways:

❌ Cannot find module '@hookform/resolvers/zod'
❌ Could not find a declaration file for module
❌ Import "ZodSchema" is deprecated in Zod v4

Root causes:

Issue Affected
Sub-path exports not resolving Vite, Next.js 13+, TS projects
Deprecated Zod imports Zod v4+ users
Bundler resolution quirks ESM/CJS mixed environments

The Solution

zod-resolver-lite is a self-contained, ~50-line resolver that:

  • βœ… Has zero sub-path import magic β€” just works
  • βœ… Uses only modern, non-deprecated Zod APIs
  • βœ… Ships as pure ESM with TypeScript declarations
  • βœ… Can be copy-pasted into your project if you prefer

πŸ§ͺ Testing

We use Vitest with 100% coverage of critical paths:

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # With coverage report

Test Coverage

Feature Status
Schema passes β†’ returns values βœ…
Schema fails β†’ returns errors βœ…
Nested array paths items[0].name βœ…
criteriaMode: "all" βœ…

πŸ—οΈ Build

npm run build

Outputs to dist/:

  • index.js β€” ESM bundle
  • index.d.ts β€” TypeScript declarations

🀝 Contributing

Contributions are welcome! Feel free to:

  1. πŸ› Report bugs
  2. πŸ’‘ Suggest features
  3. πŸ”§ Submit PRs
# Clone & install
git clone https://github.com/foudhilriahi/zod-resolver-lite.git
cd zod-resolver-lite
npm install

# Run tests
npm test

πŸ“„ License

MIT Β© foudhilriahi


If this helped you, consider giving it a ⭐

Made with ❀️ for the React Hook Form + Zod community

About

A tiny, dependency-free Zod resolver for React Hook Form

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages