كيفية استبعاد خاصية من النوع في TypeScript: إنقاذ الكود من الحمولة الزائدة
\n\nهل سبق لك أن واجهت موقفًا حيث لديك واجهة أو نوع كبير، وتحتاج إلى إنشاء نوع جديد مشابه تقريبًا ولكن بدون حقل أو حقلين؟ هل تكرر الكود بأكمله؟ هل تنسخ 15 سطرًا وتحذف واحدًا؟ هناك طريقة أكثر أناقة. اليوم سنشرح كيفية استبعاد خاصية من النوع في TypeScript - وهي واحدة من أكثر الأدوات المساعدة شيوعًا التي تنقذ من التكرار وتجعل الكود أنظف.
\n\nهذا الموضوع هو من أكثر المواضيع رواجًا على Stack Overflow. سؤال "Exclude property from type" يحصل على آلاف المشاهدات، لأن كل مطور عاجلاً أم آجلاً يواجه الحاجة إلى إزالة حقل من النوع أو استبعاد خاصية من الواجهة. دعنا نتعلم بالترتيب، بدءًا من الأمثلة البسيطة وصولاً إلى التقنيات المتقدمة.
\n\nالمشكلة: لماذا نستبعد الحقول من النوع؟
\n\nتخيل أن لديك واجهة User:
interface User {\n id: number;\n name: string;\n email: string;\n password: string;\n createdAt: Date;\n}\n\nتريد إنشاء نموذج تسجيل، حيث يدخل المستخدم الاسم والبريد الإلكتروني وكلمة المرور. لكن id يتم إنشاؤه على الخادم، و createdAt تلقائيًا. تحتاج إلى نوع NewUser الذي يحتوي فقط على name و email و password. كيف تفعل ذلك؟
الحل السيئ هو تعريف واجهة جديدة من الصفر:
\n\ninterface NewUser {\n name: string;\n email: string;\n password: string;\n}\n\nهذا يعمل، لكنه ينتهك مبدأ DRY (Don't Repeat Yourself). إذا غيرنا نوع name في User، فسيتعين علينا تغييره أيضًا في NewUser. وهنا يأتي دور استبعاد الخصائص من النوع.
النوع المساعد Omit: الأداة الرئيسية
\n\nيوفر TypeScript النوع المساعد المدمج Omit<Type, Keys>. ينشئ نوعًا جديدًا عن طريق استبعاد المفاتيح المحددة من النوع الأصلي. الصيغة بسيطة:
type NewUser = Omit<User, 'id' | 'createdAt'>;\n\nالآن NewUser يحتوي فقط على name و email و password. إذا غيرنا email إلى Email في User، فإن NewUser سيلتقط ذلك تلقائيًا.
دعنا نتحقق عمليًا:
\n\nconst newUser: NewUser = {\n name: 'آنا',\n email: 'anna@example.com',\n password: 'secure123'\n}; // ✅ كل شيء جيد\n\nconst invalidUser: NewUser = {\n name: 'آنا',\n email: 'anna@example.com',\n password: 'secure123',\n id: 1 // ❌ خطأ: id غير موجود في النوع NewUser\n};\n\nملاحظة: Omit يعمل مع كل من الواجهات والأنواع. إنها أداة عالمية لـ استبعاد الحقول من النوع.
كيف يعمل Omit من الداخل؟
\n\nلفهم أفضل لكيفية استبعاد TypeScript للخصائص من النوع، دعنا نلقي نظرة من الداخل. Omit هو مزيج من أداتين مساعدتين أخريين: Pick و Exclude.
هكذا تم تعريفه في المكتبة القياسية لـ TypeScript:
\n\ntype Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;\n\nدعنا نحللها خطوة بخطوة:
\n- \n
keyof T- يحصل على جميع مفاتيح النوع T (مثل'id' | 'name' | 'email' | 'password' | 'createdAt') \n Exclude<keyof T, K>- يستبعد من هذه المفاتيح تلك المحددة في K (نحصل على'name' | 'email' | 'password') \n Pick<T, ...>- يختار من T فقط المفاتيح المتبقية \n
وبالتالي، فإن استبعاد خاصية من الواجهة يتحول إلى تصفية المفاتيح. أنيق، أليس كذلك؟
\n\nPick: الجانب الآخر من Omit
\n\nأحيانًا يكون من الأسهل عدم الاستبعاد، بل الع