شرح تقنيات البرمجة الوصفية في TypeScript

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

1. استخدام Generics للترميز المرن

تسمح العناصر العامة للوظائف والفئات بالعمل مع مجموعة متنوعة من الأنواع، مما يزيد من المرونة وإمكانية إعادة استخدام الكود. من خلال تقديم معلمات النوع، يمكننا جعل الكود الخاص بنا عامًا مع الحفاظ على أمان النوع.

function identity<T>(arg: T): T {
  return arg;
}

const num = identity<number>(42);
const str = identity<string>("Hello");

في هذا المثال، يسمح <T> لوظيفة identity بقبول أي نوع وإرجاع نفس النوع، مما يضمن المرونة وسلامة النوع.

2. استدلال النوع والأنواع الشرطية

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

type IsString<T> = T extends string ? true : false;

type Test1 = IsString<string>;  // true
type Test2 = IsString<number>;  // false

في هذا المثال، IsString هو نوع شرطي يتحقق مما إذا كان النوع T المعطى يمتد إلى string. ويعيد true للسلاسل وfalse للأنواع الأخرى.

3. أنواع مُخططة

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

type ReadOnly<T> = {
  readonly [K in keyof T]: T[K];
};

interface User {
  name: string;
  age: number;
}

const user: ReadOnly<User> = {
  name: "John",
  age: 30,
};

// user.name = "Doe";  // Error: Cannot assign to 'name' because it is a read-only property.

هنا، ReadOnly هو نوع مُعيَّن يجعل جميع خصائص النوع المعطى readonly. وهذا يضمن عدم إمكانية تعديل خصائص كائنات هذا النوع.

4. أنواع القالب الحرفية

يتيح لك TypeScript التعامل مع أنواع السلاسل باستخدام أحرف القالب. تتيح هذه الميزة البرمجة الوصفية للعمليات القائمة على السلاسل.

type WelcomeMessage<T extends string> = `Welcome, ${T}!`;

type Message = WelcomeMessage<"Alice">;  // "Welcome, Alice!"

يمكن أن تكون هذه التقنية مفيدة لإنشاء أنواع السلاسل بشكل ديناميكي، وهو أمر شائع في التطبيقات الكبيرة التي تعتمد على أنماط السلاسل المتسقة.

5. تعريفات النوع المتكرر

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

type Json = string | number | boolean | null | { [key: string]: Json } | Json[];

const data: Json = {
  name: "John",
  age: 30,
  friends: ["Alice", "Bob"],
};

في هذا المثال، Json هو نوع متكرر يمكنه تمثيل أي بنية بيانات JSON صالحة، مما يسمح بتمثيلات مرنة للبيانات.

6. ديكورات البرمجة الفوقية

تعتبر الديكورات في TypeScript شكلاً من أشكال البرمجة الوصفية المستخدمة لتعديل أو شرح الفئات والطرق. وهي تسمح لنا بتطبيق السلوك بشكل ديناميكي، مما يجعلها مثالية للتسجيل أو التحقق أو حقن التبعيات.

function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with`, args);
    return originalMethod.apply(this, args);
  };
}

class Calculator {
  @Log
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);  // Logs: "Calling add with [2, 3]"

في هذا المثال، يقوم مُزيِّن Log بتسجيل اسم الطريقة والحجج في كل مرة يتم فيها استدعاء طريقة add. وهذه طريقة فعّالة لتوسيع السلوك أو تعديله دون تغيير كود الطريقة بشكل مباشر.

خاتمة

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