סוגים מותנים של TypeScript

טיפוסים מותנים ב-TypeScript מספקים דרך ליצור טיפוסים התלויים בתנאי. הם מאפשרים גמישות ואקספרסיביות רבה יותר בהגדרות טיפוס, מה שמאפשר ליצור מודל של יחסי טיפוס מורכבים בצורה ברורה ותמציתית. מאמר זה בוחן כיצד טיפוסים מותנים פועלים ב-TypeScript ומספק דוגמאות להמחשת השימוש בהם.

מהם סוגים מותנים?

טיפוסים מותנים מאפשרים יצירה של טיפוסים שנבחרים על סמך תנאי. הן דומות להצהרות מותנות בתכנות אך פועלות ברמת הסוג. התחביר הבסיסי של סוג מותנה הוא:

type ConditionalType = T extends U ? X : Y;

בתחביר הזה:

  • T הוא הסוג הנבדק.
  • U הוא הסוג שיש להשוות מולו.
  • X הוא הסוג המוחזר אם T מרחיב את U.
  • Y הוא הסוג המוחזר אם T אינו מרחיב את U.

דוגמה בסיסית לסוגים מותנים

הנה דוגמה פשוטה לטיפוס מותנה שמחזיר טיפוסים שונים בהתבסס על האם סוג נתון הוא מחרוזת או לא:

type IsString = T extends string ? "String" : "Not a string";

type Result1 = IsString;  // Result1 is "String"
type Result2 = IsString;  // Result2 is "Not a string"

בדוגמה זו, IsString בודק אם T מרחיב את string. אם כן, התוצאה היא "String"; אחרת, זה "Not a string".

שימוש בסוגים מותנים עם סוגים גנריים

ניתן להשתמש בסוגים מותנים גם עם טיפוסים גנריים כדי ליצור הגדרות טיפוס גמישות יותר וניתנות לשימוש חוזר. לדוגמה, סוג שמחלץ את סוג ההחזרה של פונקציה:

type ReturnType = T extends (...args: any[]) => infer R ? R : never;

type FunctionType = (x: number) => string;

type Result = ReturnType;  // Result is string

בדוגמה זו, ReturnType משתמש במילת המפתח infer כדי להסיק את סוג ההחזרה R של סוג הפונקציה T. אם T הוא סוג פונקציה, ReturnType יהיה סוג ההחזרה; אחרת, ברירת המחדל היא לעולם.

סוגים מותנים עם סוגי איגוד

טיפוסים מותנים יכולים לעבוד גם עם סוגי איגוד כדי לטפל במספר סוגים אפשריים. לדוגמה, הבחנה בין חברי איגוד שונים:

type ExtractString = T extends string ? T : never;

type UnionType = string | number | boolean;

type Result = ExtractString;  // Result is string

בדוגמה זו, ExtractString מחלץ string מסוג איחוד UnionType, וכתוצאה מכך string.

סוגים מותנים עם מיפויי סוגים

ניתן לשלב סוגים מותנים עם מיפויי סוגים כדי ליצור טרנספורמציות טיפוסיות מורכבות יותר. לדוגמה, מיפוי על מערך של טיפוסים כדי להחיל סוג מותנה:

type MapArray = {
  [K in keyof T]: T[K] extends string ? T[K] : never;
};

type ArrayType = [string, number, boolean];

type MappedArray = MapArray;  // MappedArray is [string, never, never]

בדוגמה זו, MapArray ממפה כל רכיב במערך T ומחיל סוג מותנה על כל אלמנט, וכתוצאה מכך מערך שבו רק רכיבי מחרוזת נשמרים.

מַסְקָנָה

טיפוסים מותנים ב-TypeScript הם כלי רב עוצמה ליצירת הגדרות טיפוס גמישות ואקספרסיביות. על ידי מינוף סוגים מותנים, מפתחים יכולים לדגמן קשרי סוג מורכבים, לטפל בתרחישים שונים ולשפר את בטיחות הטיפוסים בקוד ה-TypeScript שלהם. הבנה כיצד להשתמש בסוגים מותנים ביעילות יכולה לשפר משמעותית את היכולת לכתוב קוד TypeScript חזק וניתן לתחזוקה.