شرح Generics المتقدمة في TypeScript مع الأمثلة

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

القيود العامة

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

function getLength<T extends { length: number }>(arg: T): number {
    return arg.length;
}

const stringLength = getLength("TypeScript");
const arrayLength = getLength([1, 2, 3]);

في هذا المثال، يضمن القيد <T extends { length: number }> أن الوسيطة التي تم تمريرها إلى getLength تحتوي على خاصية length.

أنواع متعددة

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

function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}

const stringNumberPair = pair("TypeScript", 2024);

تقبل هذه الدالة، pair، نوعين عامين مختلفين، T وU، وترجع مجموعة تحتوي على كلا النوعين.

أنواع عامة افتراضية

يمكن أن تحتوي الأنواع العامة في TypeScript أيضًا على أنواع افتراضية. وهذا مفيد عندما تريد أن يكون للنوع العام نوع احتياطي إذا لم يتم توفير نوع محدد.

function identity<T = string>(value: T): T {
    return value;
}

const defaultString = identity("Hello");  // T is string
const customNumber = identity<number>(100);  // T is number

في هذا المثال، إذا لم يتم تمرير أي نوع إلى identity، فسيتم تعيينه افتراضيًا على string.

استخدام Generics مع الواجهات

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

interface Container<T> {
    value: T;
}

const stringContainer: Container<string> = { value: "Hello" };
const numberContainer: Container<number> = { value: 42 };

تم تصميم واجهة Container لحمل قيمة من أي نوع، مما يسمح بأنواع مختلفة من الحاويات بأنواع محددة.

الفئات العامة

يمكن أن تكون الفئات في TypeScript عامة أيضًا. وهذا مفيد بشكل خاص عند تصميم فئات تعمل مع أنواع بيانات مختلفة، مثل فئات تخزين البيانات أو فئات التجميع.

class DataStore<T> {
    private data: T[] = [];

    add(item: T): void {
        this.data.push(item);
    }

    getAll(): T[] {
        return this.data;
    }
}

const stringStore = new DataStore<string>();
stringStore.add("Hello");
stringStore.add("TypeScript");

const numberStore = new DataStore<number>();
numberStore.add(42);

في هذا المثال، تعمل فئة DataStore مع أي نوع من البيانات، مما يوفر طريقة آمنة للنوع لتخزين العناصر واسترجاعها.

خاتمة

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