الأنواع العامة (Generics) والتصنيف في JavaScript: كيفية كتابة كود خالٍ من الأخطاء

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

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

ابدأ الدورة

لماذا التصنيف هو قوة خارقة وليس عبئًا

\n\n

تخيل: أنت تكتب كودًا، كل شيء يعمل، أنت سعيد. ثم فجأة! — خطأ أحمر في وحدة التحكم: Cannot read property 'name' of undefined. مألوف؟ مرحبًا بك في عالم JavaScript بدون أنواع. لكن هناك خبر جيد: JavaScript الحديثة (وخاصة TypeScript) تقدم أداة قوية — Generics (الأنواع العامة). هذه ليست مجرد "ميزة أخرى"، بل طريقة حقيقية لجعل الكود أنظف وأكثر أمانًا وأوضح.

\n\n

في هذه المقالة، سنشرح ما هو التصنيف في JavaScript، وكيف تعمل الأنواع العامة (generics) ولماذا يجب استخدامها في كل مشروع. لا نظرية جافة — فقط أمثلة حية ونصائح عملية.

\n\n

ما هي الأنواع العامة (Generics) ولماذا نحتاجها؟

\n\n

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

\n\n

بدون الأنواع العامة، كنت ستكتب شيئًا مثل:

\n\n
function identity(arg: any): any {\n    return arg;\n}
\n\n

المشكلة؟ any يقتل كل التصنيف. تفقد معلومات النوع، ولن يتمكن المترجم من تحذيرك من الخطأ. مع Generics الأمر مختلف تمامًا:

\n\n
function identity<T>(arg: T): T {\n    return arg;\n}\n\n// الاستخدام\nlet num = identity<number>(42); // النوع number\nlet str = identity<string>("مرحبًا"); // النوع string
\n\n

سحر؟ لا، مجرد تصنيف ذكي. النوع T هو عنصر نائب يتم استبداله بالنوع الفعلي عند استدعاء الدالة.

\n\n

Generics ضد any: معركة من أجل الأمان

\n\n

يسأل الكثير من المبتدئين: "لماذا نتعب أنفسنا مع الأنواع العامة، إذا كان بإمكاننا استخدام any؟" الإجابة بسيطة: أمان الأنواع ليس من أجل "أن يكون جميلًا"، بل لمنع الأخطاء في وقت التشغيل.

\n\n

انظر إلى هذا المثال بدون Generics:

\n\n
function getLength(data: any): number {\n    return data.length; // إذا كانت data رقمًا، سيكون هناك خطأ\n}\n\ngetLength(42); // undefined في وقت التشغيل\n
\n\n

مع الأنواع العامة، تحدد بوضوح أن الدالة تعمل مع المصفوفات أو السلاسل النصية:

\n\n
function getLength<T extends { length: number }>(data: T): number {\n    return data.length;\n}\n\ngetLength([1,2,3]); // 3\ngetLength("hello"); // 5\n// getLength(42); // خطأ في الترجمة — الرقم لا يحتوي على length\n
\n\n

هل ترى الفرق؟ يتم اكتشاف الخطأ في مرحلة كتابة الكود، وليس في بيئة الإنتاج. هذا هو جوهر التصنيف المتقدم.

\n\n

أمثلة عملية على Generics في JavaScript

\n\n

دعنا نستعرض بعض السيناريوهات الواقعية حيث تنقذ الأنواع العامة الموقف حقًا.

\n\n

1. دوال عامة (Generic functions) للعمل مع المصفوفات

\n\n

لنفترض أنك تكتب أداة لاستخراج العنصر الأول من مصفوفة:

\n\n
function first<T>(arr: T[]): T | undefined {\n    return arr[0];\n}\n\nconst numbers = [10, 20, 30];\nconst firstNum = first(numbers); // النوع number | undefined\n\nconst strings = ["a", "b", "c"];\nconst firstStr = first(strings); // النوع string | undefined\n
\n\n

بدون الأنواع العامة، كان عليك كتابة دالتين منفصلتين أو استخدام any. مع تصنيف JavaScript عبر Generics — دالة واحدة تعمل مع جميع الأنواع.

\n\n

2. فئات عامة (Generic classes) لتخزين البيانات

\n\n

تخيل أنك تنشئ غلافًا بسيطًا لتخزين قيمة:

\n\n
class Box<T> {\n    private content: T;\n\n    constructor(initial: T) {\n        this.content = initial;\n    }\n\n    getValue(): T {\n        return this.content;\n    }\n\n    setValue(value: T): void {\n        this.content = value;\n    }\n}\n\n// الاستخدام\nconst numberBox                

المدونات

توصيات الكتب