الجينيريكس في TypeScript

الجينيريكس في TypeScript

تشرح هذه المقالة الجينيريكس في TypeScript۔

YouTube Video

الجينيريكس في TypeScript

الجينيريكس في TypeScript هي ميزة تتيح لك تعريف وظائف وفئات وواجهات قابلة لإعادة الاستخدام وآمنة من ناحية النوع من خلال تمرير الأنواع كمعاملات۔ استخدام الجينيريكس يسمح لك بكتابة كود لا يعتمد على أنواع محددة، مما يتيح لك أداء نفس العمليات على أنواع متعددة۔

أساسيات الجينيريكس

تعمل الجينيريكس مثل القوالب التي تقبل الأنواع كمعاملات، مما يسمح للوظائف والفئات بالتعامل مع أنواع مختلفة۔

الوظائف الجينيريك

فيما يلي مثال لوظيفة يتم فيها تحديد أنواع المعاملات باستخدام الجينيريكس۔

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity<number>(42));       // 42
6console.log(identity<string>("Hello"));  // Hello
  • T هو معامل نوع جينيريك يمثل أنواع المعاملات وقيمة الإرجاع للوظيفة۔ يتم تحديد النوع الفعلي عند استدعاء الوظيفة۔
  • من خلال تحديد <number> أو <string> صراحةً، فأنت تقوم بتحديد النوع۔

تعمل الأنواع الجينيريك دون تحديد صريح لأن TypeScript يقوم باستنتاج الأنواع۔

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity(42));       // 42
6console.log(identity("Hello"));  // Hello

قيود الجينيريكس

من خلال وضع قيود على الجينيريكس، يمكنك تقييدها بقبول أنواع محددة فقط۔

1function loggingIdentity<T extends { length: number }>(arg: T): T {
2    console.log(arg.length);
3    return arg;
4}
5
6loggingIdentity("Hello");  // 5
7loggingIdentity([1, 2, 3]);  // 3
8
9// loggingIdentity(42);  // Error: number does not have a length property.
  • تحديد T extends { length: number } يشير إلى أن T يجب أن يكون نوعًا يحتوي على خاصية length۔ لذلك، الأنواع التي لا تحتوي على خاصية length لن يتم قبولها۔

الفئات الجينيريك

يمكن أيضًا تعريف الفئات باستخدام الجينيريكس۔ تقدم الفئات الجينيريك أنواعًا مرنة للخصائص والطرق۔

 1class Box<T> {
 2    private _value: T;
 3
 4    constructor(value: T) {
 5        this._value = value;
 6    }
 7
 8    public getValue(): T {
 9        return this._value;
10    }
11
12    public setValue(value: T): void {
13        this._value = value;
14    }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue());  // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue());  // Hello
  • Box<T> تعلن عن النوع T المستخدم داخل الفئة كجينيريك۔ يتيح ذلك إعادة استخدام نفس الفئة لأنواع مختلفة۔

واجهات الجينيريك

يمكن أيضًا استخدام الجينيريكس مع الواجهات۔

 1interface Pair<T, U> {
 2    first: T;
 3    second: U;
 4}
 5
 6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
 7console.log(numberStringPair);  // { first: 1, second: 'One' }
 8
 9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair);  // { first: true, second: [ 1, 2, 3 ] }
  • من خلال تحديد نوعين جينيريك باستخدام Pair<T, U>، يمكنك تعريف كائن يجمع بين أنواع مختلفة۔

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

من الممكن أيضًا تحديد نوع افتراضي لمعاملات النوع العامة۔

1function createArray<T = string>(length: number, value: T): T[] {
2    return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a"));   // ['a', 'a', 'a']
6console.log(createArray(3, 100));   // [100, 100, 100]
  • نقوم بتعيين معامل النوع الافتراضي إلى string باستخدام <T = string>۔ إذا لم يتم تحديد النوع صراحةً، سيكون T من نوع string۔

أسماء مستعارة للنوع العام

يمكن أيضًا استخدام الأنواع العامة كأسماء مستعارة للنوع (type

 1type Result<T> = {
 2    success: boolean;
 3    data: T;
 4};
 5
 6const successResult: Result<number> = { success: true, data: 42 };
 7const errorResult: Result<string> = { success: false, data: "Error occurred" };
 8
 9console.log(successResult);  // { success: true, data: 42 }
10console.log(errorResult);    // { success: false, data: 'Error occurred' }
  • Result<T> تمثل كائن نتيجة يحتوي على بيانات من النوع T۔ بهذه الطريقة، يمكنك إنشاء أسماء مستعارة لأنواع مرنة باستخدام الأنواع العامة۔

أنواع متعددة عامة

باستخدام أنواع عامة متعددة، يمكنك تعريف وظائف وفئات أكثر مرونة۔

1function merge<T, U>(obj1: T, obj2: U): T & U {
2    return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged);  // { name: 'Alice', title: 'Engineer' }
  • تأخذ وظيفة merge نوعين مختلفين T وU وتدمجهما لإرجاع كائن جديد۔

الملخص

  • الأنواع العامة تتيح كتابة كود قابل لإعادة الاستخدام وآمن من حيث الأنواع عبر التعامل مع الأنواع كمعاملات۔
  • من خلال استخدام الأنواع العامة في الوظائف، الفئات، والواجهات، يمكنك كتابة منطق مرن يتعامل مع أنواع متعددة۔
  • من خلال إضافة قيود على معاملات النوع أو تعيين معاملات النوع الافتراضية، يمكنك التحكم في نطاق الأنواع العامة۔

من خلال استخدام الأنواع العامة، يمكنك كتابة كود غير معتمد على نوع معين وعام الغرض، مستفيداً من نظام الأنواع القوي في TypeScript۔

يمكنك متابعة المقالة أعلاه باستخدام Visual Studio Code على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔

YouTube Video