סוגים מובנים הם תכונה סינטקסטית מעניינת בטYPEscript. למרות שהם מופיעים באותו מקום כמו תוויות סוג השיחזור, הם נראים יותר כמשפטים קצרים ומוכחים מאשר תוויות סוג הרגילות. זה נותן לך שליטה רבה יותר על בדיקת סוגים.
עם השיחזור של TypeScript 5.5, עבודתם עם סוגים נעשתה יותר אינטואיטיבית עכשיו בגלל שהיא מבינה אותם באופן אוטומטי במקרים רבים. אבל אם אתה מתקדם בקוד קצת ישנה, סביר שאתה תופעל עם סוגים מותווים ידנית יותר פעמים.
במאמר הזה, נראה בקצרה מהם סוגים ומדוע הם שימושיים. בואו נתחיל בהסתכלות על הבעיה שהם פותרים.
הבעיה
אני מאמין שהדרך הטובה ביותר להבין את השימוש בסוגים היא בדיוק על הבעיות שמתרחשים בלעדם:
function isString(value: unknown): boolean {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string | number
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// string | number
}
כאן, סוג השיחזור של isString
נקבע לboolean
, ואנחנו משתמשים בו בפונקציה שנקראת padLeft
כדי להוסיף הגדלה משמאל למשתמש של טופס קטן. הpadding
יכול להיות מילה נתנת או מספר ספציפי של תווים חלקים.
ייתכן שאתה תוהה מדוע קידדתי באופן קשיח את סוג ההחזרה ל-boolean
. זה כדי להמחיש את הבעיה. אם לא תוסיף שום הערת סוג החזרה ותשתמש בגרסה העדכנית ביותר של TypeScript, לא תבחין בשום בעיה כאן. לעת עתה, סבלנות – נדון בהבדלים הקשורים לגרסה בקרוב.
הפונקציה תעבוד בצורה חלקה בזמן הריצה, אבל TypeScript לא יכול לבצע צמצום סוג עם isString
. כתוצאה מכך, סוג padding
נשאר string | number
גם בתוך וגם מחוץ ל-if
. זה מוביל לקונפליקט עם הציפייה של repeat
לגבי הארגומנט הראשון שלה, מה שגורם לשגיאת סוג.
הפתרון: הכירו את Type Predicates
אפילו אם אינך מכיר את המונח predicate, סביר להניח שכבר השתמשת בהם בעבר. Predicates בתכנות הם פשוט פונקציות שמחזירות ערך בוליאני כדי לענות על שאלה של כן/לא. כמה שיטות מובנות במערך של JavaScript, כגון filter
, find
, every
, ו-some
, משתמשות ב-predicates כדי לסייע בקבלת החלטות.
Type predicates הם דרך להפוך את ה-predicates לשימושיים יותר לצמצום סוג. נוכל לפתור את הבעיה על ידי שימוש ב-type predicate כסוג ההחזרה:
function isString(value: unknown): value is string {
return typeof value === "string";
}
כאן ה-type predicate הוא value is string
. הוא אומר שלושה דברים:
-
הפונקציה היא predicate. לכן TypeScript תציג שגיאה אם תנסה להחזיר משהו שאינו ערך בוליאני.
-
אם זה מחזיר
true
, אזvalue
הוא מסוג של משפט. -
אם זה מחזיר
false
, אזvalue
אינו מסוג של משפט.
מנחומים סוגייה מאפשרים לך ליצור מערכים מדגימים סוג. מערכים מדגימים הם בדיקות הגיוניות שמאפשרות לך להתאים סוגים לסוגים יותר ספציפיים, למשל להתאים אותם. כך שהפונקציה העליונה היא גם מערכת מדגימה מוגדרה על-ידיך.
הנה הקוד המלא:
function isString(value: unknown): value is string {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// משפט
}
return " ".repeat(padding) + input;
// ^
// מספר
}
כאן, TypeScript מצמצם בצורה נכונה את סוג הpadding
בתוך ההצעהif
ובחוץ.
עכשיו בואו נסתכל בקצרה כיצד היו מנחומים סוגייה לפני TypeScript 5.5 ומה הדבר שהגדלה בגירסה הזאת.
מנחומים סוגייה לפני TypeScript 5.5
בדוגמה הקודמת, אם אינך מספק סוג שיחזרה, הוא יוצע כboolean
:
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// משפט | מספר
}
return " ".repeat(padding) + input; // אופס שגיאה סוג כאן
// ^
// משפט | מספר
}
וכתוצאה מכך, יש לנו את אותו השגיאה שהיתה כשכתבנו באופן ידני הסוג החזרה boolean
. כאן הקישור למגרש המשחק של TypeScript עבור הפיסת הקוד הקודמת. לכם להגיע ולהציץ על הפונקציות או המשתנות עבור הרגשה טובה יותר על הסוגים. ואז ראו איך כתיבת המדידה הסוגית פתרון הבעיה.
אם לא נציין את המדידה הסוגית, בשימוש בשיטות כמו filter
יכול גם להוביל לזיהוי סוג שגוי:
function isString(value: unknown) {
return typeof value === "string";
}
const numsOrStrings = [1, 'hello', 2, 'world'];
// ^
// strings: (string | number)[]
const strings = numsOrStrings.filter(isString);
// ^
// strings: (string | number)[]
עכשיו בואו נראה איך TypeScript 5.5 משפר את המצב.
מדדים סוגיים אחרי TypeScript 5.5
אחד התכונות העליונות של TypeScript 5.5 היא שהיא יכולה להסיק מדדים סוגיים על-ידי ניתוח את הגוף הפונקציוני. אז אם אתם משתמשים ב TypeScript 5.5 או אחריו, אתם לא צריכים לכתוב את המדידה הסוגית בתור סוג החזרה של isString
. TypeScript עושה את זה בשבילכם, והקוד שאתם רואים בדוגמה הבאה עובד בדיוק טוב:
function isString(value: unknown) {
return typeof value === "string";
}
function padLeft(padding: number | string, input: string) {
if (isString(padding)) {
return padding + input;
// ^
// string
}
return " ".repeat(padding) + input; // Opps type error here
// ^
// number
}
const numsOrStrings = [1, 'hello', 2, 'world'];
const strings = numsOrStrings.filter(isString);
// ^
// strings: string[]
const numbers = numsOrStrings.filter((v) => !isString(v));
// ^
// numbers: number[]
עדיין לא מצאתי מצב בו אני לא מרוצה מההסתברות האוטומטית של הדיקות הסוגיות. אם תמצאו אחד, תוכלו תמיד לכתוב את העצמי באופן ידני.
למידה נוספת
במאמר זה, בודקנו בקצרה את הדיקות הסוגיות בטייפסקript. אם אתה מעוניין ללמוד יותר ולהבין את המקרים הקצוצים, הנה המדריכים הרשמיים:
תודה רבה על הקריאה! נראה לנו בפעם הבאה!
רקע התמונה מקורו בMona Eendra על Unsplash.
Source:
https://www.freecodecamp.org/news/what-are-type-predicates-in-typescript/