🔷 شرح TypeScript

الأنواع المتقدّمة

الأنواع الشرطية (Conditional Types)

نوع يعتمد على شرط، بصيغة T extends U ? X : Y:

type IsString<T> = T extends string ? "نعم" : "لا";

type A = IsString<string>;   // "نعم"
type B = IsString<number>;   // "لا"

مثال عملي — استخراج نوع العنصر من مصفوفة:

type ElementType<T> = T extends (infer U)[] ? U : T;

type X = ElementType<number[]>;   // number
type Y = ElementType<string>;     // string

infer يستنتج نوعًا داخل الشرط ويسمّيه U لاستخدامه.

الأنواع المُعيَّنة (Mapped Types)

تنشئ نوعًا جديدًا بالمرور على مفاتيح نوع موجود:

type Flags = {
  darkMode: boolean;
  notifications: boolean;
};

// اجعل كل الحقول اختيارية
type Optional<T> = {
  [K in keyof T]?: T[K];
};

type PartialFlags = Optional<Flags>;
// { darkMode?: boolean; notifications?: boolean }

هكذا تُبنى الأنواع المساعدة مثل Partial وReadonly داخليًّا:

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

تعديل المفاتيح أثناء التعيين

// تحويل كل القيم إلى string
type Stringify<T> = {
  [K in keyof T]: string;
};

الأنواع النصّية القالبية (Template Literal Types)

type Color = "red" | "blue";
type Shade = `light-${Color}`;   // "light-red" | "light-blue"

متى تستخدم هذه الأنواع؟

غالبًا لن تكتبها يدويًّا كثيرًا — لكنها تشغّل المكتبات والأنواع المساعدة التي تستخدمها يوميًّا. فهمها يجعلك قارئًا أفضل لأنواع المكتبات.

أخطاء شائعة

  • المبالغة في الأنواع المتقدّمة لمشاكل بسيطة — ابدأ بالأبسط.
  • نسيان أن infer تُستخدم فقط داخل الأنواع الشرطية.

🎯 التالي: البرمجة غير المتزامنة (Async) بالأنواع.