Zod ilə TypeScript Runtime Validasiyası: Bugları Production-da Deyil, Əvvəlcədən Tut
TypeScript compile-time-da tip yoxlayır, amma runtime-da API-dən gələn datanı kim yoxlayacaq? Zod ilə validasiyanı necə həll edəcəyini real nümunələrlə göstərirəm.
Problemin kökü: TypeScript sənə yalan danışmır, amma hər şeyi bilmir
Bakıda bir fintech startupda işləyirsən. Backend komanda sənə deyir ki, API response-da amount field-i number olacaq. Sən TypeScript-də interface yazırsan, hər şey gözəl görünür. Deploy edirsən. Bir həftə sonra production-da amount: "1500" — string kimi gəlir. UI qırılır, müştəri şikayət edir, PM qrupda sənə tag atır.
Tanış gəldi?
Problem ondadır ki, TypeScript yalnız compile-time-da işləyir. Kod JavaScript-ə çevrildikdən sonra heç bir tip yoxlaması qalmır. API-dən, form-dan, localStorage-dən, WebSocket-dən gələn data — hamısı runtime-da any kimidir. Məhz bu boşluğu Zod doldurur.
Zod nədir və niyə hamı istifadə edir?
Zod — TypeScript-first schema validation kitabxanasıdır. 2025-ci ilin Stack Overflow Developer Survey-inə görə, TypeScript layihələrinin 38%-i artıq Zod və ya oxşar runtime validation kitabxanasından istifadə edir. npm-də həftəlik yükləmə sayı 25 milyonu keçib.
Zod-un əsas üstünlükləri:
- Zero dependency — heç bir asılılığı yoxdur
- TypeScript-first — schema-dan avtomatik tip çıxarır
- Kiçik ölçü — gzipped ~13KB
- Zəngin ekosistem — React Hook Form, tRPC, Next.js ilə inteqrasiya
Quraşdırma sadədir:
bashnpm install zod
İlk schema-nı yazaq
Tutaq ki, Bakıdakı bir e-commerce platformada işləyirsən və istifadəçi sifarişlərini validate etməlisən:
typescriptimport { z } from "zod"; const OrderSchema = z.object({ orderId: z.string().uuid(), customerName: z.string().min(2, "Ad minimum 2 simvol olmalıdır"), amount: z.number().positive("Məbləğ müsbət olmalıdır"), currency: z.enum(["AZN", "USD", "EUR"]), items: z.array( z.object({ productId: z.string(), quantity: z.number().int().min(1), price: z.number().nonnegative(), }) ).min(1, "Minimum 1 məhsul olmalıdır"), deliveryAddress: z.string().min(10), phone: z.string().regex(/^\+994(50|51|55|70|77)\d{7}$/, "Düzgün Azərbaycan nömrəsi daxil edin"), createdAt: z.string().datetime(), }); // Schema-dan TypeScript tipini avtomatik çıxar type Order = z.infer<typeof OrderSchema>;
Diqqət et: z.infer ilə schema-dan avtomatik TypeScript tipi yaradırıq. Interface ilə schema-nı ayrı-ayrı yazmağa ehtiyac yoxdur. Bu, DRY prinsipini qoruyur.
Runtime-da necə istifadə olunur?
API-dən gələn datanı parse edək:
typescriptasync function processOrder(rawData: unknown) { const result = OrderSchema.safeParse(rawData); if (!result.success) { // Xətaları strukturlaşdırılmış şəkildə al const errors = result.error.flatten(); console.error("Validasiya xətaları:", errors.fieldErrors); // Məsələn: { phone: ["Düzgün Azərbaycan nömrəsi daxil edin"] } return { success: false, errors: errors.fieldErrors }; } // result.data artıq tam tipləşdirilmiş Order-dir const order: Order = result.data; console.log(`Sifariş qəbul edildi: ${order.amount} ${order.currency}`); await saveToDatabase(order); return { success: true, orderId: order.orderId }; }
.safeParse() exception atmır — nəticəni success boolean ilə qaytarır. Production-da bu yanaşma daha təhlükəsizdir. Əgər xətanın atılmasını istəyirsənsə, .parse() istifadə edə bilərsən.
Real layihə pattern-ləri
1. Environment variables validasiyası
Bunu hər layihədə etməlisən. Ciddi deyirəm — hər layihədə:
typescriptconst EnvSchema = z.object({ DATABASE_URL: z.string().url(), API_KEY: z.string().min(20), PORT: z.string().transform(Number).pipe(z.number().int().min(1000).max(65535)), NODE_ENV: z.enum(["development", "staging", "production"]), }); // App başlayanda validate et const env = EnvSchema.parse(process.env); export default env;
Bu pattern ilə deployment zamanı .env faylında nəsə əskik olsa, app dərhal xəta verib dayanacaq — 3 saat sonra random crash əvəzinə.
2. API response validasiyası
typescriptconst UserResponseSchema = z.object({ id: z.number(), email: z.string().email(), balance: z.number().default(0), role: z.enum(["user", "admin", "moderator"]).default("user"), createdAt: z.string().datetime().transform((str) => new Date(str)), }); async function fetchUser(id: number) { const response = await fetch(`/api/users/${id}`); const json = await response.json(); // Backend nə göndərirsə göndərsin, biz validate edirik return UserResponseSchema.parse(json); }
3. Form validasiyası (React Hook Form + Zod)
Bu kombinasiya Azərbaycanda da, dünyada da standart halına gəlib:
typescriptimport { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; const LoginSchema = z.object({ email: z.string().email("Düzgün email daxil edin"), password: z.string().min(8, "Minimum 8 simvol"), }); type LoginForm = z.infer<typeof LoginSchema>; function LoginPage() { const { register, handleSubmit, formState: { errors } } = useForm<LoginForm>({ resolver: zodResolver(LoginSchema), }); const onSubmit = (data: LoginForm) => { // data artıq 100% validate olunub console.log(data); }; // ... JSX }
Zod vs alternativlər
| Kitabxana | Ölçü (gzip) | TypeScript-first | Performans |
|---|---|---|---|
| Zod | ~13KB | ✅ Bəli | Yaxşı |
| Yup | ~15KB | ❌ Sonradan | Yaxşı |
| Joi | ~28KB | ❌ Xeyr | Orta |
| Valibot | ~5KB | ✅ Bəli | Əla |
Əgər bundle size kritikdirsə, Valibot-a bax — API oxşardır, amma tree-shaking ilə çox kiçik olur. Amma ekosistem və community baxımından Zod hələ ki liderdir.
Bakı developer bazarında Zod bilikləri
Son bir il ərzində LinkedIn-dəki Azərbaycan iş elanlarına baxsanız, TypeScript tələb edən vakansiyalarda Zod və ya runtime validation biliyinə tələbin artdığını görəcəksiniz. Xüsusilə ABB, Kapital Bank, Paşa Holding-in texnoloji komandaları, eləcə də Bakıdakı outsource şirkətləri — Next.js, tRPC stack-ləri istifadə edən komandalar Zod-u mütləq tələb edir.
1800-3500 AZN aralığında olan middle/senior frontend vakansiyalarında TypeScript artıq default tələbdir. Zod bilmək sizi fərqləndirən əlavə dəyər ola bilər — xüsusilə müsahibədə "API-dən gələn datanı necə validate edirsiniz?" sualına as SomeType əvəzinə Zod schema göstərsəniz, fərqli görünəcəksiniz.
Nəticə: runtime-da da güvən
TypeScript — dostundur, amma hər yerdə səni qoruya bilmir. Runtime validation — production buglarının qarşısını alan real müdafiə xəttidir.
Bugünkü addımların:
- Mövcud layihəndə
npm install zodet - Ən kritik API endpoint-ini Zod schema ilə validate et
- Environment variables-ı validate etməyə başla
- Yavaş-yavaş bütün external data boundary-lərini Zod ilə örtək
Bir dəfə vərdiş etsən, Zod-suz layihəyə baxanda narahat olacaqsan. Bu, yaxşı əlamətdir.
Sualın varsa, şərhlərdə yaz. Növbəti məqalədə tRPC + Zod ilə end-to-end type safety haqqında danışacağıq.
Oxşar məqalələr
TypeScript ilə Supabase inteqrasiyası — tam tip təhlükəsizliyi
Supabase + TypeScript birlikdə işlədəndə runtime xətaları minimuma enir. Database-dən gələn hər sətir tipli olur. Necə? Bu məqalədə.
TypeScript Generics — Nədir, Niyə Lazımdır, Necə İstifadə Olunur?
TypeScript generics-i başa düşmək Bakıda frontend və backend vakansiyaların 70%-ində tələb olunan skilldir. Bu bələdçi ilə generics-i bir dəfəlik öyrən.
Azərbaycan Fintech Startaplarında TypeScript: Niyə 2026-da Bu Bacarıq Sənə Lazımdır
Bakıda fintech sektoru böyüyür, TypeScript bilikli developer-lərə tələbat artır. Real kod nümunələri və maaş rəqəmləri ilə niyə indi keçid etməli olduğunu izah edirik.