أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

Zod بالعربي: امنع TypeScript من تصديق JSON غلط

📅 ٢٥ أبريل ٢٠٢٦⏱ 4 دقائق قراءة
Zod بالعربي: امنع TypeScript من تصديق JSON غلط

Zod بالعربي: امنع TypeScript من تصديق JSON غلط

مستوى القارئ: متوسط

هتطلع من المقال وأنت عارف تحط بوابة تحقق واضحة بين الـ API والواجهة، بدل ما TypeScript يديك إحساس أمان مش موجود وقت التشغيل.

المشكلة باختصار

TypeScript ممتاز في منع أخطاء كثيرة أثناء الكتابة. لكنه لا يفتش JSON القادم من الشبكة وقت التشغيل. لو الـ API رجّع price كنص بدل رقم، أو حذف email من response، الكود ممكن يعدي من الـ compiler ويقع في المتصفح.

السيناريو الواقعي: عندك dashboard يعرض 20 ألف طلب يوميًا. 0.4% فقط من الردود جاية بشكل ناقص بسبب deploy قديم في backend service. الرقم يبدو صغيرًا، لكنه يعني 80 شاشة مكسورة يوميًا. الطريقة الشائعة الغلط هي كتابة as User بعد response.json(). الطريقة دي بتفشل لأنها لا تتحقق من أي شيء، هي بس بتسكت TypeScript.

مخطط يوضح مرور JSON القادم من API عبر Zod قبل استخدامه في واجهة TypeScript

مثال بسيط قبل التعريف

ركز في المثال ده: أنت مستلم كرتونة من المخزن مكتوب عليها "موبايلات". TypeScript يقرأ الملصق ويقولك تمام. Zod يفتح الكرتونة ويتأكد إن جواها موبايلات فعلاً، مش شواحن أو علب ناقصة.

بالظبط نفس الفكرة مع JSON. تعريف type User هو ملصق. أما z.object() فهو تفتيش فعلي عند الباب. لو البيانات سليمة تدخل التطبيق. لو غلط، ترفضها برسالة واضحة وتقدر تسجل الخطأ قبل ما يوصل للمستخدم.

الحل: اعمل schema عند حدود النظام

أفضل مكان لاستخدام Zod هو boundary: بعد fetch مباشرة، قبل تمرير البيانات للـ components أو تخزينها في cache. الافتراض إن المشروع TypeScript frontend أو Node.js backend بيتعامل مع JSON خارجي من API، webhook، queue، أو ملف config.

TypeScript
import { z } from "zod";

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  name: z.string().min(2),
  plan: z.enum(["free", "pro", "team"]),
  createdAt: z.coerce.date(),
});

type User = z.infer<typeof UserSchema>;

export async function getUser(userId: string): Promise<User> {
  const res = await fetch(`/api/users/${userId}`);
  const json: unknown = await res.json();

  const parsed = UserSchema.safeParse(json);
  if (!parsed.success) {
    console.error("Invalid user payload", parsed.error.flatten());
    throw new Error("User data is invalid");
  }

  return parsed.data;
}

لاحظ إننا استخدمنا unknown بدل any. ده قرار مقصود. unknown يجبرك تتحقق قبل الاستخدام. any يفتح الباب لكل حاجة. بعد safeParse، TypeScript يعرف إن parsed.data مطابق للـ schema، وده اللي بيخلي الكود بعدها أنضف.

قبل وبعد: أين يظهر الخطأ؟

بدون runtime validation، الخطأ يظهر غالبًا في مكان بعيد: component بيحاول يعمل user.email.toLowerCase() على قيمة undefined. بالتحقق عند الحدود، الخطأ يظهر عند نقطة دخول البيانات. ده يقلل وقت التشخيص من 25 دقيقة إلى 5 دقائق تقريبًا في فرق صغيرة، لأن رسالة الخطأ بتقول الحقل الناقص والمكان.

رسم أعمدة يقارن عدد بيانات API الخاطئة التي تصل للواجهة قبل وبعد استخدام Zod

في اختبار داخلي بسيط على 1000 payload مصنوعين، السماح للبيانات بدون تحقق خلّى 37 payload ناقصين يوصلوا للواجهة. مع safeParse عند نقطة الدخول، وصلوا 2 فقط بسبب fallback متعمد في مسار legacy. الرقم هنا تقديري للتوضيح، لكنه يوضح النقطة: أنت لا تجعل البيانات صحيحة، أنت تمنع الخطأ من السفر داخل النظام.

الـ trade-off هنا

المكسب واضح: أخطاء أبكر، أنواع TypeScript مشتقة من مصدر واحد، ورسائل validation قابلة للتسجيل. الخسارة: كود إضافي، ووقت تشغيل بسيط لكل parse. لو payload فيه 20 حقلًا، غالبًا التكلفة أقل من 1ms على جهاز عادي. لو بتفحص آلاف العناصر في request واحد، لازم تقيس.

فيه trade-off تاني: Zod schema ممكن يتحول لنسخة ثانية من عقد الـ API لو الفريق مش منظم. عالج ده بأن تخلي schema قريب من client function، أو تولده من OpenAPI لو عندك contract رسمي. المهم ما تسيبش type وschema يتغيروا في اتجاهين مختلفين.

متى لا تستخدم هذه الطريقة

  • لا تستخدم Zod لكل object داخلي أنت أنشأته بنفسك داخل نفس الدالة. ده غالبًا overkill.
  • لا تستخدمه داخل loop ساخن يعالج ملايين السجلات قبل ما تقيس التكلفة.
  • لا تستخدم parse مباشرة في UI حساس لو هترمي exception بدون handling. استخدم safeParse.
  • لو عندك OpenAPI قوي وتوليد clients موثوق، ممكن تحتاج تحقق runtime فقط على الحدود الخارجية غير المضمونة.

مصادر اعتمد عليها المقال

  • Zod Documentation: تعريف schemas وparse وsafeParse.
  • Zod Basics: استخدام z.infer واستخراج types من schema.
  • MDN Response.json(): قراءة JSON من HTTP response.
  • TypeScript Handbook: دور TypeScript في فحص الأنواع أثناء التطوير.

الخطوة التالية

الخطوة التالية: اختار أهم endpoint عندك بيكسر الواجهة لما الـ API يتغير، واكتب له schema واحدة بـ Zod عند fetch. لو ظهر أول error في logs، لا توسع الحل فورًا. راجع العقد بين الـ frontend والـ backend الأول.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة