Аднаўленне аднаго шымата Zod між фронтэндам на React і бэкендам на Node.
Дазвольце даклэ на адзін шымат Zod можна пераверыць формы React, адпаведныя адпаведзіцеў API, тэлы запытак Express і зменныя сераўіса, адночасна ствараючы адпаведныя типы TypeScript.
Параболіка неабяжна ў кожным прыкладзе практычнага выкарыстоўвання, але команды часта прымушаны ўстановіць яе поступова — адна бібліятэка для фронтэнда, іншая — для бэкэнда, а тыя ж правілы копіююцца і вставляюцца ў разныя месцы. Zod стаў падабаным средства між разработчыкамі JavaScript і TypeScript самэўсёле таму, што ён узбегае такой хаос: вы пішыце адну схему, і гэтая схема як пераканальвае вашы данні, так і стварае адпаведны тип TypeScript, які можна выкарыстоўваць аднойчы і ў браузеры, і на серверы.
1. Чаму ёсць Zod?
Zod — это бібліятэка схем, створаная з самага пачатку з урахоўваннем TypeScript. Вы описваеце формат сваіх дадзеных аднойчы, і Zod выкарыстоўвае гэты опис для пераканальвання значэнняў у час выконання і для автаматычнага стварэння типу TypeScript — няма неабязковай інтэрфейсу, які трэба пісаць, і няма рызыку таго, што ён не будзе супараднаўацца з вашымі правіламі параболіка.
import { z } from 'zod';
const UserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
type User = z.infer<typeof UserSchema>;
// { name: string; email: string; age?: number }
Такій адміністратыўны лямбэт можа адразу паводліваць тры функцыі: ён дакументуе структуру дадзеных, прыменяе яе пад час выканання та забезпечвае статычны тип, на які рэгулююцца редактар і кампайляр.
2. Чаму Zod працюе краща за іншыя альтэрнатывы
Галоўная перадчыннае ўмеласць — автаматычная інферэнція типаў. Бібліятекі на кшталт Yup чы Joi зазвычай вымагаюць, каб вы падтрымвалі схему верыфікацыі разам з рукапісным інтерфейсам на TypeScript, пакладаючыся на тое, што гэтыя два элементы не будуць адступаць одны ад другога праз змены ў кодбазе. Zod цэлкам усуняе гэты рызык: тип выводзіцца безпасова з самай схемы, таму няма нічога, што трэба синхронізаваць.
Zod таксама легкі і не маюць зовнішніх залежнасцей, што робіць яго такім жа зручным у пакетах фронтэнду, дзе важліва меры розмяру, як і ў сервісах Node.js. Яго можна складваць у ланцюг, а API дазваляе выплываць нават складную верыфікацыю — вярстакаваныя об’екты, з’еднання, поля, якіе залежаць адзіна ад другога — так, каб усё заставалася чытаемым, а не ператварылася на клубок спецыяльных дапаможных функцый.
3. Испытанне Zod у дапрыемку React
3.1 Верыфікацыя формы з React Hook Form
Zod можа быць прыўязаны безпасова да React Hook Form за дапамогою пакета @hookform/resolvers.
npm install zod react-hook-form @hookform/resolvers
// components/SignupForm.tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const SignupSchema = z.object({
name: z.string().min(2, 'Name is too short'),
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
});
type SignupData = z.infer<typeof SignupSchema>;
export function SignupForm() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<SignupData>({
resolver: zodResolver(SignupSchema),
});
const onSubmit = (data: SignupData) => {
console.log('Valid data:', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} placeholder="Name" />
{errors.name && <p>{errors.name.message}</p>}
<input {...register('email')} placeholder="Email" />
{errors.email && <p>{errors.email.message}</p>}
<input type="password" {...register('password')} placeholder="Password" />
{errors.password && <p>{errors.password.message}</p>}
<button type="submit">Sign Up</button>
</form>
);
}
Няма ручнага стэрагавання статусу адзіны і няма падвойных заяваў пра типы, якія трэба падтрымваць — адна схема адрабатвае перакананне, задае паведамленні пра адзіны, якія паказваюцца ля кожнага поля, і адразу ж вядома типавуюе об’ект data, які быў адправлены, у TypeScript.
3.2 Перакананне адпаведнасці адказаў API
Zod таксама ўжыткавы на вхіднай стороне вашага прыемніка — напрыклад, калі трэба пераканацца, што даныя, якія вярнуліся з API, дэйсна падходзяць таму, чаго вы чакалі, адколі нельга паспакоўвацца толькі типамі на час кампілявання, ўбеджаючыся в этом.
import { z } from 'zod';
const PostSchema = z.object({
id: z.number(),
title: z.string(),
body: z.string(),
});
const PostsResponseSchema = z.array(PostSchema);
async function fetchPosts() {
const res = await fetch('/api/posts');
const json = await res.json();
const result = PostsResponseSchema.safeParse(json);
if (!result.success) {
console.error(result.error.flatten());
throw new Error('Invalid API response shape');
}
return result.data; // fully typed Post[]
}
Этый падчынак дазваляе зафіксав некоректныя або неспадзеваныя адпаведзіць прытаму, перш чым яны спрычыняюць тыхія бяды ў вашай інтэрфейсе.
4. Іспылака Zod у сервере Node.js / Express
4.1 Аверыфікацыя тэла запитоў
npm install zod express
// schemas/user-schema.ts
import { z } from 'zod';
export const CreateUserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
export type CreateUserInput = z.infer<typeof CreateUserSchema>;
// middleware/validate.ts
import { Request, Response, NextFunction } from 'express';
import { ZodSchema } from 'zod';
export function validate(schema: ZodSchema) {
return (req: Request, res: Response, next: NextFunction) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.flatten() });
}
req.body = result.data;
next();
};
}
// routes/users.ts
import { Router } from 'express';
import { validate } from '../middleware/validate';
import { CreateUserSchema } from '../schemas/user-schema';
const router = Router();
router.post('/users', validate(CreateUserSchema), (req, res) => {
// req.body is now guaranteed to match CreateUserInput
const { name, email, age } = req.body;
res.status(201).json({ name, email, age });
});
export default router;
Гэта налаштаванне дае кожнаму маршруту аднообразны, декларатыўны крок аверыфікацыі, пры чым обработка бядаў централізавана, а не павтараецца як лінейныя if-пераказы ў кожным хэндлеры.
4.2 Аверыфікацыя зменных сэраўису
Адзін недаабраны, але эфектыўны спосаб выкарыстоўвання Zod — гэта перагляд process.env пад час запуску аплікацыі, таким чынам паказваючы некоректную настройку і спрычыняючы негайную паўстаноўку, замест таго каб пазней з’явіўся незрозумелы баг.
// config/env.ts
import { z } from 'zod';
const EnvSchema = z.object({
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(['development', 'production', 'test']),
});
export const env = EnvSchema.parse(process.env);
Якщо якая-небудзь неабходная зменна відсутня або мае некоректны формат, процес негайна падупае з чытаемым поведамленням пра адказ — гэта набагато лёгкае для діагназавання, чым таўарныя паўстаноўкі, якія выкаліваюцца пад час вызову базы дадзенаў.
5. Асалоджэнне: адна схема, якая выкорыстоўваецца ў всім стэйку
Паколькі схемы Zod — гэта проста значэнні TypeScript, ніч не заважае разместіць іх у спяльнай пакетазе — або ў спяльной папцы ўнутрь монорепо — і пераўтарна выкарыстоўваць точна такую ж схему як у кліенте, так і на серверы.
/packages
/shared
/schemas
user-schema.ts <-- used by both React app and Express API
/web (React/Next.js)
/api (Node/Express)
// packages/shared/schemas/user-schema.ts
import { z } from 'zod';
export const CreateUserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
age: z.number().int().positive().optional(),
});
export type CreateUserInput = z.infer<typeof CreateUserSchema>;
React-аплікацыя выкорыстоўвае гэтую схему для пераканання формы рэўізіі пры яе адправцы. API Express таксама выкорыстоўвае тую ж самую схему для пераверкі прыходзячых дадзенняў. Калі схема зміняецца — напрыклад, падыходзіць новая обавязкова ячэйка — абе слоі адразу ж реагуюць на змяну, а TypeScript негайна выяўляе ўсі код, які ўжо не прыстосаваўся да новага формата. Чыгунам гэта закрывае цэлую клясу бягоў, калі пераверкі з боку кліента і сервера па часе таямна адступаюць адзін ад другога.
6. Найкращыя практыкі
- Выбірайце
safeParse, калі неудача є нормальным, прыемлівым рэзультатам (вхідныя даны формы, адпаведзі трэціх сторон), аparse, який выклекае адказ, застаўляйце для ситуацыяў, якія практычна ніколи не можуць быць некоректнымі, напрыклад, для зменных сяродовышча, якія пераканваюцца пад час запуску.
.transform() для чысткі падаўленых дадзенняя як частку самай пераканальні — адсечванне прасоў, прымусовая канвертазія типаў — замест таго, каб пасля гэтага запускаць адзінокы процес нормалізацыі.z.infer працоўней, чым ручна напісаныя інтэрфейсы, каб вашы типы і логіка пераканальні ніколі не выйшлі з сінхрону.error.flatten() або error.format(), чым код фронтэнду будзе лёгка асоціяваць кожны паказанні з правым полем формы.7. Заключэнне
Zod — гэта не проста стандартная бібліятэка для верыфікацыі; яна цалкам зменяе адносы между верыфікацыёй і заданнем типаў. Генеруючы типы TypeScript безпасцельна з схем, якія выкарыстоўваюцца пад час адработкі данных, яна усуняе проблему рознаковасці падзэльных заданняў типаў і правілаў верыфікацыі. Да гэтага яе мінімальны розмах, можлівасць складання з іншымі компонентамі, а таксама стабільнае працаванне як у браузеры, так і ў Node робяць Zod ідеальным выборам для проектаў на TypeScript з архітэктурай full-stack, пабудаваных на React і Node.js.
Наступныя крокі:
- Якщо вам трэба генеравацыя дакументацыі OpenAPI безпасцельна з вашых схем, паглядзіце на
zod-to-openapi - Для стварэння спецыяльной логікі верыфікацыі, якая распрастараецца на калькі полей, выкорыстоўваюце
.refine()і.superRefine() - Паглядзіце на tRPC — ён апытна выкарыстоўвае схемы Zod для забезпечэння безпекі типаў на всіх етапах працы вашай API
Спадні матэрыялы
- Zod vs express-validator: Два падходы да верыфікацыі дадзеных у Express — Пораўнанне верыфікацыі запытакаў на адной основе схемы з Zod і мідлвэра express-validator, які работае на адной ланцуговай основе; раскрываюцца аспекты настройкі, форматаванняя памылак і распасцеленыя проблемы.
- Прапанаванні TC39 у 2026 годзе: Декоратары, Temporal і Signals — пояснення — Практычны аналіз трох прапанаванняў TC39 — натыўных декоратароў, API Temporal і Signals — і якія ўплывы яны маюць для разработчыкаў JavaScript і TypeScript у фул-стак-сераўсе.