Generics في JavaScript: لماذا تحتاجها وكيف تستخدمها للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

ما هي Generics في JavaScript ولماذا تحتاجها؟

\n\n

تخيل أنك تكتب دالة يجب أن تعمل مع أنواع مختلفة من البيانات - الأرقام، النصوص، الكائنات. بدون Generics (الجينيريكس)، سيكون عليك إما تكرار الكود أو استخدام any، مما يفقدك السيطرة على الأنواع. Generics هي آلية تسمح لك بإنشاء مكونات (دوال، كلاسات، واجهات) تعمل مع أي نوع بيانات، ولكن مع الحفاظ على معلومات النوع.

\n\n

على الرغم من أن JavaScript هي لغة ذات كتابة ديناميكية، إلا أن نظام Node.js يستخدم بنشاط TypeScript، الذي يضيف الكتابة الثابتة. في TypeScript، تتجلى قوة الجينيريكس بشكل كامل. ومع ذلك، فإن فهم مبادئها مفيد حتى لـ JavaScript النقي - خاصة إذا كنت تكتب مكتبات أو تعمل مع أطر العمل الحديثة.

\n\n

في هذه المقالة، سنشرح:

\n
    \n
  • لماذا تحتاج Generics
  • \n
  • كيفية تعريف واستخدام الجينيريكس في TypeScript
  • \n
  • أمثلة لـ Node.js (API، معالجة البيانات)
  • \n
  • القيود وأفضل الممارسات
  • \n
\n\n

أساسيات Generics: الصيغة والأمثلة الأساسية

\n\n

أول جينيريك: دالة الهوية

\n\n

المثال الكلاسيكي - دالة تعيد ما تستقبله:

\n\n
// بدون Generics\nfunction identity(value: any): any {\n  return value;\n}\n\n// مع Generics\nfunction identity<T>(value: T): T {\n  return value;\n}\n\n// الاستخدام\nconst num = identity<number>(42);    // num هو number\nconst str = identity<string>('مرحباً'); // str هو string\n
\n\n

الرمز <T> هو معامل النوع. يمكنك تسميته كما تشاء (T، U، Item)، لكن التقاليد تتطلب استخدام T (من Type).

\n\n

جينيريكس مع عدة معاملات

\n\n

أحياناً تحتاج للعمل مع عدة أنواع في وقت واحد:

\n\n
function pair<T, U>(first: T, second: U): [T, U] {\n  return [first, second];\n}\n\nconst result = pair<number, string>(1, 'واحد');\n// result: [number, string]\n
\n\n

جينيريكس في الدوال السهمية (Node.js)

\n\n

في React أو الأدوات المساعدة، غالباً ما تستخدم الدوال السهمية مع الجينيريكس:

\n\n
const wrapInArray = <T>(item: T): T[] => {\n  return [item];\n};\n\nconst arr = wrapInArray('اختبار'); // arr: string[]\n
\n\n

تطبيق Generics في مشاريع Node.js الحقيقية

\n\n

معالجات API مع استجابات محددة الأنواع

\n\n

تخيل أنك تكتب دالة عامة للاستعلامات إلى API. بدون الجينيريكس، ستفقد أنواع البيانات:

\n\n
// سيء: any\nasync function fetchData(url: string): Promise<any> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// جيد: Generics\nasync function fetchData<T>(url: string): Promise<T> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// الاستخدام\ninterface User {\n  id: number;\n  name: string;\n}\n\nconst user = await fetchData<User>('/api/user/1');\nconsole.log(user.name); // TypeScript يعلم أن name هو string\n
\n\n

مجموعات بيانات محددة الأنواع

\n\n

عند العمل مع قواعد البيانات (مثل Prisma أو Mongoose)، تساعد الجينيريكس في إنشاء مستودعات عامة:

\n\n
class Repository<T extends { id: number }> {\n  private items: T[] = [];\n\n  add(item: T): void {\n    this.items.push(item);\n  }\n\n  getById(id: number): T | undefined {\n    return this.items.find(item => item.id === id);\n  }\n}\n\n// الاستخدام\ninterface Product {\n  id: number;\n  title: string;\n  price: number;\n}\n\nconst productRepo = new Repository<Product>();\nproductRepo.add({ id: 1, title: 'لابتوب', price: 1000 });\nconst laptop = productRepo.getById(1);\n
\n\n

أغلفة لمعالجة الأخطاء

\n\n

دالة عامة لـ

المدونات

توصيات الكتب