Deterministic validation layer ensuring that all data entering the system conforms to the defined architectural contracts.
Benefits: Zod allows combining runtime validation with TypeScript typing, creating a single source of truth for forms and API data.
Located in the schema folder. Files are named following the [name].schema.ts pattern. Schemas are named in uppercase (e.g., ENTITY_SCHEMA).
Located in the types folder. Types inferred from schemas are named with a T prefix (e.g., TEntitySchema). All form field enums are stored in ENUM_FORM_... objects.
Creating a Zod object using i18nKey for localized error messages.
1import { z } from "zod";
2import { type TEntityPageKeys, i18nKey } from "@/shared/config";
3import { ENUM_FORM_ENTITY } from "../types";
4
5const msg = i18nKey<TEntityPageKeys>();
6
7export const ENTITY_SCHEMA = z.object({
8 [ENUM_FORM_ENTITY.DESCRIPTION]: z
9 .string()
10 .trim()
11 .min(1, {
12 message: msg("form.overview.fields.description.errors.required")
13 })
14 .min(3, {
15 message: msg("form.overview.fields.description.errors.min")
16 })
17 .max(5000, {
18 message: msg("form.overview.fields.description.errors.max")
19 }),
20});Using z.infer to automatically generate TypeScript types from the schema.
1import { z } from "zod";
2import type { ENTITY_SCHEMA } from "../schema";
3
4export const ENUM_FORM_ENTITY = {
5 DESCRIPTION: "description",
6} as const;
7
8export type TEntitySchema = z.infer<typeof ENTITY_SCHEMA>;Connecting the schema to react-hook-form via zodResolver.
1import { useForm } from "react-hook-form";
2import { zodResolver } from "@hookform/resolvers/zod";
3import { type TEntitySchema, ENTITY_SCHEMA } from "@/entities/entity-name";
4
5const form = useForm<TEntitySchema>({
6 resolver: zodResolver(ENTITY_SCHEMA),
7 mode: "onSubmit"
8});