العربية

تعلم كيفية توسيع أنواع TypeScript للمكتبات الخارجية باستخدام تعزيز الوحدات، مما يضمن أمان الأنواع ويحسن تجربة المطور.

تعزيز وحدات TypeScript: توسيع أنواع المكتبات الخارجية

تكمن قوة TypeScript في نظام الأنواع القوي الخاص بها. فهو يمكّن المطورين من اكتشاف الأخطاء مبكرًا، وتحسين قابلية صيانة الكود، وتعزيز تجربة التطوير الشاملة. ومع ذلك، عند العمل مع مكتبات خارجية، قد تواجه سيناريوهات تكون فيها تعريفات الأنواع المقدمة غير مكتملة أو لا تتوافق تمامًا مع احتياجاتك الخاصة. هنا يأتي دور تعزيز الوحدات (module augmentation) لإنقاذ الموقف، مما يسمح لك بتوسيع تعريفات الأنواع الحالية دون تعديل كود المكتبة الأصلي.

ما هو تعزيز الوحدات؟

تعزيز الوحدات هو ميزة قوية في TypeScript تمكّنك من إضافة أو تعديل الأنواع المعلنة داخل وحدة نمطية (module) من ملف مختلف. فكر في الأمر على أنه إضافة ميزات إضافية أو تخصيصات لفئة أو واجهة موجودة بطريقة آمنة من حيث النوع. هذا مفيد بشكل خاص عندما تحتاج إلى توسيع تعريفات أنواع المكتبات الخارجية، وإضافة خصائص أو دوال جديدة، أو حتى تجاوز الموجودة لتعكس متطلبات تطبيقك بشكل أفضل.

على عكس دمج الإعلانات (declaration merging)، الذي يحدث تلقائيًا عند وجود إعلانين أو أكثر بنفس الاسم في نفس النطاق، يستهدف تعزيز الوحدات بشكل صريح وحدة نمطية معينة باستخدام صيغة declare module.

لماذا نستخدم تعزيز الوحدات؟

إليك الأسباب التي تجعل تعزيز الوحدات أداة قيمة في ترسانة TypeScript الخاصة بك:

كيف يعمل تعزيز الوحدات

يدور المفهوم الأساسي حول صيغة declare module. إليك الهيكل العام:


declare module 'module-name' {
  // إعلانات الأنواع لتعزيز الوحدة
  interface ExistingInterface {
    newProperty: string;
  }
}

دعنا نحلل الأجزاء الرئيسية:

أمثلة عملية

مثال 1: توسيع مكتبة طرف ثالث (Moment.js)

لنفترض أنك تستخدم مكتبة Moment.js للتعامل مع التاريخ والوقت، وتريد إضافة خيار تنسيق مخصص لمنطقة معينة (على سبيل المثال، لعرض التواريخ بتنسيق معين في اليابان). قد لا تتضمن تعريفات أنواع Moment.js الأصلية هذا التنسيق المخصص. إليك كيف يمكنك استخدام تعزيز الوحدات لإضافته:

  1. تثبيت تعريفات الأنواع لـ Moment.js:
    
    npm install @types/moment
    
  2. إنشاء ملف TypeScript (على سبيل المثال، moment.d.ts) لتعريف تعزيزك:
    
    // moment.d.ts
    import 'moment'; // استيراد الوحدة الأصلية لضمان توفرها
    
    declare module 'moment' {
      interface Moment {
        formatInJapaneseStyle(): string;
      }
    }
    
  3. تنفيذ منطق التنسيق المخصص (في ملف منفصل، على سبيل المثال، moment-extensions.ts):
    
    // moment-extensions.ts
    import * as moment from 'moment';
    
    moment.fn.formatInJapaneseStyle = function(): string {
      // منطق التنسيق المخصص للتواريخ اليابانية
      const year = this.year();
      const month = this.month() + 1; // الشهر يبدأ من 0
      const day = this.date();
      return `${year}年${month}月${day}日`;
    };
    
  4. استخدام كائن Moment.js المعزز:
    
    // app.ts
    import * as moment from 'moment';
    import './moment-extensions'; // استيراد التنفيذ
    
    const now = moment();
    const japaneseFormattedDate = now.formatInJapaneseStyle();
    console.log(japaneseFormattedDate); // المخرجات: على سبيل المثال، 2024年1月26日
    

الشرح:

مثال 2: إضافة خصائص إلى كائن الطلب (Express.js)

لنفترض أنك تستخدم Express.js وتريد إضافة خاصية مخصصة إلى كائن Request، مثل userId الذي يتم ملؤه بواسطة وسيط (middleware). إليك كيف يمكنك تحقيق ذلك باستخدام تعزيز الوحدات:

  1. تثبيت تعريفات الأنواع لـ Express.js:
    
    npm install @types/express
    
  2. إنشاء ملف TypeScript (على سبيل المثال، express.d.ts) لتعريف تعزيزك:
    
    // express.d.ts
    import 'express'; // استيراد الوحدة الأصلية
    
    declare module 'express' {
      interface Request {
        userId?: string;
      }
    }
    
  3. استخدام كائن Request المعزز في وسيطك:
    
    // middleware.ts
    import { Request, Response, NextFunction } from 'express';
    
    export function authenticateUser(req: Request, res: Response, next: NextFunction) {
      // منطق المصادقة (على سبيل المثال، التحقق من JWT)
      const userId = 'user123'; // مثال: استرداد معرف المستخدم من الرمز
      req.userId = userId; // تعيين معرف المستخدم لكائن الطلب
      next();
    }
    
  4. الوصول إلى خاصية userId في معالجات المسارات الخاصة بك:
    
    // routes.ts
    import { Request, Response } from 'express';
    
    export function getUserProfile(req: Request, res: Response) {
      const userId = req.userId;
      if (!userId) {
        return res.status(401).send('Unauthorized');
      }
    
      // استرداد ملف تعريف المستخدم من قاعدة البيانات بناءً على userId
      const userProfile = { id: userId, name: 'John Doe' }; // مثال
      res.json(userProfile);
    }
    

الشرح:

مثال 3: إضافة سمات مخصصة إلى عناصر HTML

عند العمل مع مكتبات مثل React أو Vue.js، قد ترغب في إضافة سمات مخصصة إلى عناصر HTML. يمكن أن يساعدك تعزيز الوحدات في تحديد أنواع هذه السمات المخصصة، مما يضمن أمان الأنواع في قوالبك أو كود JSX.

لنفترض أنك تستخدم React وتريد إضافة سمة مخصصة تسمى data-custom-id إلى عناصر HTML.

  1. إنشاء ملف TypeScript (على سبيل المثال، react.d.ts) لتعريف تعزيزك:
    
    // react.d.ts
    import 'react'; // استيراد الوحدة الأصلية
    
    declare module 'react' {
      interface HTMLAttributes extends AriaAttributes, DOMAttributes {
        "data-custom-id"?: string;
      }
    }
    
  2. استخدام السمة المخصصة في مكونات React الخاصة بك:
    
    // MyComponent.tsx
    import React from 'react';
    
    function MyComponent() {
      return (
        
    This is my component.
    ); } export default MyComponent;

الشرح:

أفضل الممارسات لتعزيز الوحدات

المزالق الشائعة وكيفية تجنبها

فوائد استخدام تعزيز الوحدات

يوفر استخدام تعزيز الوحدات في TypeScript العديد من الفوائد الرئيسية:

الخلاصة

يعتبر تعزيز الوحدات في TypeScript تقنية قوية لتوسيع وتخصيص تعريفات الأنواع من المكتبات الخارجية. باستخدام تعزيز الوحدات، يمكنك ضمان بقاء الكود الخاص بك آمنًا من حيث النوع، وتحسين تجربة المطور، وتجنب تكرار الكود. من خلال اتباع أفضل الممارسات وتجنب المزالق الشائعة التي نوقشت في هذا الدليل، يمكنك الاستفادة بشكل فعال من تعزيز الوحدات لإنشاء تطبيقات TypeScript أكثر قوة وقابلية للصيانة. اغتنم هذه الميزة واطلق العنان للإمكانات الكاملة لنظام أنواع TypeScript!