A tiny, dependency-free Zod resolver for React Hook Form
Drop-in replacement for @hookform/resolvers/zod
when you hit import errors, bundler issues, or TypeScript headaches.
Features β’ Installation β’ Usage β’ API β’ Why This Exists
| 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 |
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| Package | Version |
|---|---|
zod |
^4.0.0 |
react-hook-form |
^7.0.0 |
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>
);
}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"] β
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"
// }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
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 |
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
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| Feature | Status |
|---|---|
| Schema passes β returns values | β |
| Schema fails β returns errors | β |
Nested array paths items[0].name |
β |
criteriaMode: "all" |
β |
npm run buildOutputs to dist/:
index.jsβ ESM bundleindex.d.tsβ TypeScript declarations
Contributions are welcome! Feel free to:
- π Report bugs
- π‘ Suggest features
- π§ Submit PRs
# Clone & install
git clone https://github.com/foudhilriahi/zod-resolver-lite.git
cd zod-resolver-lite
npm install
# Run tests
npm testMIT Β© foudhilriahi
If this helped you, consider giving it a β
Made with β€οΈ for the React Hook Form + Zod community