دوال السهم في TypeScript مع الأنواع العامة (Generics): دليل كامل مع أمثلة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كود أقل، فائدة أكبر: فهم دوال السهم والأنواع العامة في TypeScript



هل سبق لك أن كتبت أداة صغيرة في TypeScript كان يجب أن تعمل مع الأرقام والنصوص والمصفوفات؟ واجهت على الفور مشكلة: كيف تجعل نوع البيانات مرنًا، ولكن دون أن يشتكي TypeScript؟ الإجابة هي الأنواع العامة (generics، أو الأنواع المعممة). وإذا كنت تحب بناء الجملة المختصر، فمن المحتمل أنك تستخدم دوال السهم.



ولكن هناك مشكلة: على Stack Overflow، السؤال «What is the syntax for Typescript arrow functions with generics?» حصل على آلاف المشاهدات. اتضح أنه حتى المطورين ذوي الخبرة يخلطون أحيانًا في هذا المزيج الذي يبدو بسيطًا. في هذه المقالة، سنفهم كيفية كتابة TypeScript arrow functions مع الأنواع العامة بشكل صحيح، ونستعرض الأخطاء الشائعة، ونوضح كيف تجعل كودك أنظف وأكثر أمانًا.



مستعد؟ لنبدأ!



ما هي الأنواع العامة في دوال السهم؟



بدايةً - شرح موجز. تسمح الأنواع العامة بإنشاء مكونات (دوال، كلاسات، واجهات) تعمل مع أنواع مختلفة، وليس مع نوع واحد محدد. بدلاً من كتابة دوال منفصلة للأرقام والنصوص، تكتب دالة واحدة - بنوع عام.



دوال السهم (arrow functions) هي بناء جملة مضغوط للدوال في JavaScript و TypeScript. عندما تدمجها مع الأنواع العامة، تحصل على أداة قوية لإنشاء أدوات قابلة لإعادة الاستخدام.



// دالة عادية بنوع عامfunction identity<T>(arg: T): T {    return arg;}

// دالة سهم بنوع عام - كيف تبدو؟const arrowIdentity = <T>(arg: T): T => arg;


أمر بسيط؟ نعم، ولكن هناك تفاصيل دقيقة سنشرحها أدناه.



بناء الجملة الأساسي: كيفية تعريف TypeScript arrow function مع generics بشكل صحيح



الطريقة الأبسط والأكثر شيوعًا هي تحديد معامل النوع (النوع العام) قبل الأقواس المستديرة التي تحتوي على الوسائط:



const firstElement = <T>(arr: T[]): T | undefined => {    return arr[0];};

// الاستخدامconst num = firstElement([1, 2, 3]); // type: number | undefinedconst str = firstElement(['a', 'b']); // type: string | undefined


هنا <T> هو تعريف النوع العام. سيقوم TypeScript تلقائيًا باستنتاج النوع T بناءً على الوسيطة المُمررة. إذا أردت تحديد النوع بشكل صريح، فهذا يعمل أيضًا:



const num = firstElement<number>([1, 2, 3]); // نحدد النوع بشكل صريح


هام: في JSX (React)، قد يتعارض هذا البناء مع ترميز JSX. هناك حلول بديلة لهذه الحالات (سنتناولها أدناه).



أنواع عامة متعددة في دالة سهم واحدة



يمكنك استخدام عدة معاملات أنواع:



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

const result = pair(42, 'hello'); // type: [number, string]


هذا مفيد بشكل خاص عند العمل مع أدوات مثل map، reduce أو عند إنشاء أغلفة.



مشاكل مع JSX (React) وحلها



إذا كنت تكتب في React مع TypeScript، ستلاحظ أن بناء الجملة <T>(arg) قد يفسره المترجم كوسم JSX. هذه مشكلة كلاسيكية، ولهذا السبب حظي السؤال على Stack Overflow بهذه الشعبية.



هناك حلان رئيسيان:



1. استخدام extends (حتى لو لم يكن ضروريًا)



أضف extends unknown أو extends Record<string, never>:



const myFunction = <T extends unknown>(arg: T): T => {    return arg;};


هذا يوضح لـ TypeScript أن <T> هو نوع عام وليس JSX.



2. استخدام بناء الجملة بفاصلة



في بعض الحالات، يساعد إضافة فاصلة بعد النوع العام:



const myFunction = <T,>(arg: T):                

المدونات

توصيات الكتب