TypeScript export مقابل default export: نفهم الفرق مرة واحدة وإلى الأبد
\n\nمرحباً يا صديقي! إذا كنت قد بدأت للتو رحلتك مع TypeScript (أو لم تعد مبتدئاً ولكنك لا تزال تحتار في التصدير)، فهذه المقالة هي طوق نجاة لك. موضوع "TypeScript export مقابل default export" هو من أكثر المواضيع سخونة على Stack Overflow، وليس من دون سبب. يبدو الأمر بسيطاً، لكن كم من الجدل دار حوله! دعنا نرتب الأمور ونفهمها بشكل نهائي، ونحفظ متى نستخدم export ومتى نستخدم export default.
لن نكتفي بسرد القواعد بشكل جاف. سنستعرض أمثلة حية، وأخطاء شائعة للمبتدئين، ونقدم توصيات محددة. هيا بنا!
\n\nما هو التصدير في TypeScript ولماذا نحتاجه؟
\n\nتخيل أنك تكتب برنامجاً كبيراً. هل ستضع كل الكود في ملف واحد؟ بالطبع لا. ستقسمه إلى وحدات: ملف واحد للتعامل مع المستخدمين، وآخر للحسابات، وثالث للواجهة. التصدير هو طريقة لإخبار TypeScript: "مرحباً، هذه الدالة، أو الكلاس، أو المتغير يمكن استخدامها في ملفات أخرى". أما الاستيراد فهو طريقة لإخباره: "أعطني هذه القطعة من الملف الآخر".
\n\nفي TypeScript، هناك نوعان رئيسيان من التصدير: التصدير المُسمى (named export) والتصدير الافتراضي (default export). وهنا يبدأ الجزء الممتع.
\n\nالتصدير المُسمى (named export) — الدقة والتنظيم
\n\nالتصدير المُسمى هو عندما تحدد بوضوح اسم ما تقوم بتصديره. الأمر يشبه وضع ملصق ساطع على كل صندوق في مرآبك: "أدوات"، "معدات رياضية"، "كتب دراسية قديمة".
\n\nالصيغة بسيطة جداً. فقط أضف الكلمة المفتاحية export قبل التعريف:
مثال على التصدير المُسمى
\n\n// utils.ts\nexport const PI = 3.14159;\n\nexport function calculateArea(radius: number): number {\n return PI * radius * radius;\n}\n\nexport class Circle {\n constructor(public radius: number) {}\n}\n\nوالآن لنستورد هذا في ملف آخر:
\n\n// app.ts\nimport { PI, calculateArea, Circle } from './utils';\n\nconsole.log(PI); // 3.14159\nconst area = calculateArea(5);\nconst myCircle = new Circle(10);\n\nلاحظ الأقواس المتعرجة { } عند الاستيراد. إنها علامة أكيدة على التصدير المُسمى. يمكنك استيراد ما تحتاجه فقط، ويجب عليك استخدام نفس الأسماء المحددة عند التصدير (أو إعادة تسميتها باستخدام as، لكن سنتحدث عن ذلك لاحقاً).
مزايا التصدير المُسمى
\n- \n
- الوضوح: ترى دائماً ما يتم تصديره بالضبط من الوحدة. \n
- الإكمال التلقائي: بيئة التطوير المتكاملة (IDE) مثل VS Code تقترح الأسماء بشكل ممتاز عند الاستيراد. \n
- إعادة الهيكلة: إذا أعدت تسمية دالة مصدرة، فإن IDE يعيد تسميتها في جميع أماكن الاستيراد. هذا آمن. \n
- Tree-shaking: أدوات التجميع (Webpack, Vite) يمكنها "إزالة" الكود غير المستخدم، مما يقلل حجم الحزمة النهائية. \n
التصدير الافتراضي (default export) — الراحة والاختصار
\n\nالتصدير الافتراضي هو عندما تقول: "هناك كيان رئيسي واحد في هذا الملف، وأريده أن يكون سهل الاستيراد". الأمر يشبه قولك: "هذه بطاقة عملي، عليها كل الأساسيات".
\n\nيمكن أن يكون لكل وحدة تصدير افتراضي واحد فقط. الصيغة:
\n\nمثال على التصدير الافتراضي
\n\n// logger.ts\nconst log = (message: string): void => {\n console.log(`[LOG]: ${message}`);\n};\n\nexport default log;\n\nأو يمكنك التعريف مباشرة:
\n\nexport default function log(message: string): void {\n console.log(`[LOG]: ${message}`);\n}\n\nالاستيراد يبدو هكذا (بدون أقواس متعرجة!):
\n\n// main.ts\nimport myLog from '