تخطّى إلى المحتوى الرئيسي
ما الذي تغيّر في Zod 4، وكيف رحّلنا مخططات الإنتاج

ما الذي تغيّر في Zod 4، وكيف رحّلنا مخططات الإنتاج

July 20, 2026
هندسة الويب المتكاملة
5 دقيقة قراءة

أبرز النقاط

- Zod 4 هو الإصدار الرئيسي المستقر من مكتبة التحقق من المخططات المبنية على TypeScript، صدر عام 2025، ويركّز على فحص أنواع أسرع، وتحليل أسرع في وقت التشغيل، ونواة أصغر، ويتطلب TypeScript 5.5 أو أحدث.

- صيغ النصوص أصبحت الآن دوالّ عليا قابلة لإزالة الشيفرة غير المستخدمة — z.email() و z.uuid() و z.url() — والصيغة المتسلسلة z.string().email() مهملة لكنها ما زالت تعمل.

- معامل error واحد يحلّ محل خيارات Zod 3 الأربعة: message و invalid_type_error و required_error و errorMap؛ تمرّر نصاً أو دالة تستقبل المشكلة.

- انتقلت تهيئة الأخطاء إلى ثلاث دوالّ مستقلة: z.flattenError لأخطاء حقول النموذج، و z.treeifyError للأشكال المتداخلة، و z.prettifyError لنص مقروء للبشر.

- بنية zod/mini تكشف نفس أدوات التحقق عبر واجهة وظيفية قابلة لإزالة الشيفرة غير المستخدمة للحِزم الحسّاسة للحجم، بينما لم تتغيّر z.infer و .parse() و .safeParse().

في Devya نلجأ إلى Zod في معظم المشاريع للتحقق من المدخلات غير الموثوقة عند الحدود — أجسام الطلبات، وبيانات النماذج، ومتغيرات البيئة، واستجابات واجهات الطرف الثالث. غيّر Zod 4 قدراً كافياً من الواجهة بحيث أوقعت الترقية الآلية بضعة ملفات عبر قواعد شيفرتنا، فرسمنا بدقة ما الذي تغيّر. هذه ملاحظاتنا الميدانية.

ما الذي تغيّر فعلياً في Zod 4؟

Zod 4 هو إعادة كتابة كاملة لمكتبة التحقق من المخططات المبنية على TypeScript، صدر كإصدار رئيسي مستقر عام 2025. العنوان الأبرز هو الأداء: تشير ملاحظات إصدار فريق Zod إلى انخفاض كبير في عدد إنشاءات أنواع مترجم TypeScript وإلى تحليل أسرع في وقت التشغيل، وهو ما يهم أكثر في القواعد البرمجية الكبيرة حيث تهيمن أنواع المخططات على زمن فحص الأنواع.

أربعة تغييرات في الواجهة مسّت شيفرتنا مباشرة: انتقلت صيغ النصوص إلى دوالّ عليا، وانهارت خيارات الأخطاء الأربعة في خيار واحد، وانتقلت تهيئة الأخطاء إلى دوالّ مستقلة، وتحوّلت .strict()/.passthrough() إلى z.strictObject()/z.looseObject(). كما أضاف Zod 4 بنية zod/mini للحِزم الأصغر وتحويلاً مدمجاً إلى JSON Schema عبر z.toJSONSchema().

لماذا أصبحت z.string().email() هي z.email()؟

يرقّي Zod 4 صيغ النصوص إلى دوالّ عليا مستقلة — z.email() و z.uuid() و z.url() ومساعدات ISO ضمن z.iso — بدلاً من توابع متسلسلة على z.string(). الصيغة المتسلسلة z.string().email() ما زالت تعمل لكنها مهملة وتسجّل تحذيراً.

السبب هو إزالة الشيفرة غير المستخدمة (tree-shaking): كل صيغة دالة مستقلة بذاتها، لذا فإن الحزمة التي تتحقق من البريد الإلكتروني فقط لم تعد تشحن منطق التحقق لكل صيغة أخرى لا تستخدمها. في مخطط كائن، يصبح حقل id هو z.uuid()، وحقل البريد z.email()، وموقع اختياري z.url().optional()، ويُشتقّ نوع TypeScript عبر z.infer للمخطط.

كيف أضبط رسائل الأخطاء المخصّصة في Zod 4؟

يستبدل Zod 4 أربعة خيارات منفصلة للأخطاء بمعامل error واحد. في Zod 3 كنت تمرّر message أو invalid_type_error أو required_error أو errorMap كاملاً حسب الحالة.

في Zod 4 تمرّر error واحداً: نصاً لرسالة ثابتة، أو دالة تستقبل المشكلة وتعيد رسالة. تلك الدالة الواحدة تستطيع التمييز بين قيمة مفقودة ونوع خاطئ عبر فحص ما إذا كان issue.input غير معرّف، كل ذلك في مكان واحد.

كيف أحوّل ZodError إلى أخطاء نموذج؟

ينقل Zod 4 تهيئة الأخطاء من توابع على كائن الخطأ إلى ثلاث دوالّ عليا. تعيد z.flattenError(error) كائناً فيه formErrors و fieldErrors، وهو ما ينطبق بسلاسة على رسائل الحقول في النموذج. وتعيد z.treeifyError(error) كائناً متداخلاً يعكس شكل المخطط، للبيانات العميقة التداخل. وتعيد z.prettifyError(error) نصاً متعدد الأسطر مقروءاً للبشر للسجلات وأدوات سطر الأوامر.

مصفوفة error.issues الخام لم تتغيّر، والتابعان الأقدم error.format() و error.flatten() مهملان لصالح هذه الدوالّ. معالج المسار النموذجي يستدعي safeParse على جسم الطلب؛ عند الفشل يقرأ fieldErrors من z.flattenError ويعيدها بحالة 400، وعند النجاح تكون خاصية data ذات نوع كامل.

متى نستخدم zod/mini بدلاً من حزمة zod الكاملة؟

استخدم zod/mini حين يكون حجم الحزمة مهماً — شيفرة العميل، ودوالّ الحافة، والودجات المشحونة — واستخدم حزمة zod الكاملة في كل ما عدا ذلك. تكشف zod/mini نفس أدوات التحقق عبر واجهة وظيفية: بدلاً من تسلسل .optional() تغلّف بـ z.optional()، وتستخدم التنقيحات .check() بدلاً من .refine().

هذا أكثر إسهاباً، لكن لعدم وجود سلسلة توابع تُزال الشيفرة غير المستخدمة ويصغر حجم الحزمة. تتشارك البنيتان نفس النواة، لذا يكون سلوك المخطط في وقت التشغيل متطابقاً. باختصار: توابع متسلسلة وقابلية قراءة في الحزمة الكاملة؛ ومغلّفات وظيفية وبصمة أصغر في zod/mini.

كيف ننتقل من Zod 3 دون كسر كل شيء؟

انتقل تدريجياً، لأن Zod 4 يبقي واجهات Zod 3 المهملة تعمل مع تحذيرات بدلاً من إزالتها كلياً. خلال الانتقال نشر Zod الإصدار الجديد تحت مسار الاستيراد zod/v4، في إصدار zod@3.25، بحيث يمكن للفرق تبنّيه ملفاً ملفاً قبل وصول zod@4.0؛ وتبقى الواجهة القديمة متاحة عند zod/v3.

عمليتنا: ترقية الحزمة، ثم تشغيل فاحص الأنواع ومجموعة الاختبارات، ثم إزالة تحذيرات الإهمال على دفعات — إعادة تسمية استدعاءات صيغ النصوص، ودمج خيارات الأخطاء في error واحد، وتبديل .strict()/.passthrough() إلى z.strictObject()/z.looseObject(). ولأن z.infer و .parse() و .safeParse() لم تتغيّر، بقيت معظم المخططات تعمل دون مساس.

الأسئلة الشائعة

**س:** هل أُزيلت z.string().email() في Zod 4؟

**ج:** لا. ما زالت تعمل لكنها مهملة وتسجّل تحذيراً. الصيغة الموصى بها هي z.email() العليا، وكلاهما يتحقق بنفس الطريقة.

**س:** ما الذي حلّ محل errorMap و invalid_type_error في Zod 4؟

**ج:** معامل error واحد. مرّر نصاً لرسالة ثابتة، أو دالة تستقبل المشكلة لرسائل شرطية مثل التمييز بين قيمة مفقودة ونوع خاطئ.

**س:** كيف نحصل على أخطاء على مستوى الحقول لنموذج في Zod 4؟

**ج:** استدعِ z.flattenError(error)؛ حقل fieldErrors فيه يربط كل مفتاح في المخطط برسائله. استخدم z.treeifyError(error) للأشكال العميقة التداخل.

**س:** هل zod/mini مكتبة منفصلة؟

**ج:** لا. إنها بنية من Zod 4 بنفس أدوات التحقق مكشوفة عبر واجهة وظيفية قابلة لإزالة الشيفرة غير المستخدمة لحِزم أصغر.

**س:** هل يتطلب Zod 4 إصداراً محدداً من TypeScript؟

**ج:** نعم. يتطلب Zod 4 إصدار TypeScript 5.5 أو أحدث.

قراءات إضافية

لماذا يستمر استهلاك الذاكرة في عمليات Node بالارتفاع: ملاحظات ميدانية عن لقطات الكومة والكاش في نطاق الوحدة والتسريبات التي تظهر عند إعادة استخدام النسخ
اقرأ المقال

هندسة الويب المتكاملة

لماذا يستمر استهلاك الذاكرة في عمليات Node بالارتفاع: ملاحظات ميدانية عن لقطات الكومة والكاش في نطاق الوحدة والتسريبات التي تظهر عند إعادة استخدام النسخ

خدمة Node تبقى بصحة جيدة لساعة بعد كل نشر ثم يبدأ استهلاكها بالارتفاع تعني تسريباً فوق الطلب لا داخله. هذه ملاحظاتنا الميدانية حول التفريق بين تسريب حقيقي وتذبذب جمع المهملات، والتقاط لقطات الكومة عبر ‎--heapsnapshot-signal‎، وقراءة لوحة Retainers وصولاً إلى Map في نطاق الوحدة، ولماذا تجعل إعادة استخدام النسخ في Fluid Compute الكود بلا خادم يتسرب كخادم طويل العمر.

لماذا لا تنجح ذاكرة CDN أبدًا: ملاحظاتنا الميدانية حول Cache-Control وs-maxage وstale-while-revalidate
اقرأ المقال

هندسة الويب المتكاملة

لماذا لا تنجح ذاكرة CDN أبدًا: ملاحظاتنا الميدانية حول Cache-Control وs-maxage وstale-while-revalidate

كانت نقطة نهاية JSON عامة تصل إلى الخادم الأصلي في كل طلب بينما بدت إعدادات CDN صحيحة. هذه ملاحظاتنا الميدانية حول قراءة ترويسات x-vercel-cache وAge بدلًا من لوحات التحكم، والفرق بين max-age وs-maxage وstale-while-revalidate، ومتى تتفوق CDN-Cache-Control على ترويسة Cache-Control وحدها، والحالات الخمس التي تُعطّل التخزين على الحافة بصمت.