משפט switch ב-TypeScript הוא ה-switch של JavaScript עם בדיקת טיפוסים. הוא משווה ערך לכל case עם ===, מריץ את הענף שמתאים, ועוצר ב-break או ב-return. TypeScript מצמצם את הערך בתוך כל case ויכול לבדוק שכל ערך אפשרי מטופל.
תוויות מוערמות (case "sat": case "sun":) חולקות ענף אחד. return מסיים את הפונקציה, ולכן אין צורך ב-break אחריו.
תחביר
switch (expression) {
case value1:
// runs when expression === value1
break;
case value2:
case value3:
// runs for value2 or value3
break;
default:
// runs when nothing else matched
}
- ההתאמה משתמשת בשוויון מחמיר,
===:case 1לא מתאים למחרוזת"1". - בלי
break,returnאוthrow, הביצוע ממשיך ל-case הבא (fallthrough). defaultהוא אופציונלי ויכול לשבת בכל מקום, אם כי נהוג לשים אותו אחרון.- ערך
caseש-TypeScript יכול להוכיח שאף פעם לא יתאים הוא השגיאה TS2678. לפרמטר מטיפוס"a" | "b",case "c":מדווחType '"c"' is not comparable to type '"a" | "b"'., וזה תופס שגיאות הקלדה בתוויות.
צמצום בתוך כל case
בכל case, TypeScript יודע איזה ערך התאים ומצמצם את הטיפוס. זה הכי שימושי עם discriminated union: עשו switch על מאפיין התגית המשותף, וכל case רואה את הווריאנט המתאים עם המאפיינים שלו.
shape.radius מתקמפל רק ב-case של "circle". מחוץ לו, shape יכול להיות מלבן, שאין לו radius. אין default, והפונקציה עדיין עוברת בדיקת טיפוסים כמחזירה number, כי TypeScript רואה ששלושת ה-cases מכסים כל kind. תבניות נוספות שנבנות על זה נמצאות בעמוד discriminated unions.
switch ממצה עם never
הפונקציה למעלה מפסיקה להתקמפל אם מוסיפים צורה רביעית בלי case (TS2366, חסר return). זה עובד רק כשהפונקציה מחזירה ערך. לערובה שעובדת גם בקוד void ונותנת הודעה ברורה יותר, הוסיפו default שמשים את הערך ל-never:
index.ts(14,19): error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
אחרי ה-cases שטופלו, הטיפוס היחיד שנשאר ל-shape הוא הווריאנט של המשולש, ואי אפשר להשים אותו ל-never. השגיאה מציינת בדיוק מה חסר. הוסיפו case "triangle": return (shape.base * shape.height) / 2; וה-default רואה never, כך שהבלוק מתקמפל ומדפיס 9. ה-throw עדיין מגן מפני נתונים שגויים בזמן ריצה, כמו kind שהגיע מ-JSON והטיפוסים לא צפו אותו.
בסיסי קוד רבים עוטפים את הבדיקה בפונקציית עזר:
אותה טכניקה עובדת עם enums: עשו switch על ערך ה-enum והעבירו אותו ל-assertNever ב-default.
switch (true) לטווחים ולתנאים
switch משווה ערכים, ולכן טווחים דורשים טריק: עשו switch על true וכתבו תנאי בכל case. מאז TypeScript 5.3, התנאים האלה מצמצמים טיפוסים בדיוק כמו משפטי if.
ה-cases נבדקים לפי הסדר, אז שימו את הספציפי ביותר ראשון. אם זה קריא יותר מ-if / else if זה עניין של טעם; ההתנהגות זהה.
fallthrough ו-break
case שיש בו קוד אבל אין בו break, return או throw נופל ל-case הבא. זה כמעט תמיד באג. אפשרות הקומפיילר noFallthroughCasesInSwitch (לא חלק מ-strict) הופכת את זה לשגיאה TS7029, Fallthrough case in switch., ועדיין מתירה תוויות ריקות מוערמות.
fallthrough מכוון כזה עובד, אבל כש-noFallthroughCasesInSwitch מופעל צריך לכתוב אותו מחדש, למשל עם בדיקות if נפרדות. בדרך כלל זה גם ברור יותר.
משתנים בתוך cases
כל גוף ה-switch הוא בלוק אחד, ולכן const שהוצהר ב-case אחד נראה ב-cases האחרים (והצהרה חוזרת היא שגיאה). עטפו case בסוגריים מסולסלים כדי לתת לו scope משלו:
בלי הסוגריים, ה-const unit השני הוא שגיאת הקומפילציה TS2451, Cannot redeclare block-scoped variable 'unit'.
switch מול חיפוש באובייקט
כשכל case רק ממפה ערך לערך אחר, אובייקט עם טיפוס Record קצר יותר, ו-TypeScript בודק שכל מפתח קיים:
השמטה של מפתח היא שגיאת קומפילציה, וזה נותן את אותו מיצוי כמו בדיקת never. השאירו את switch למקרים שמריצים לוגיקה שונה, מצמצמים וריאנטים של union או חוזרים מוקדם.
שאלות נפוצות
איך כותבים משפט switch ב-TypeScript?
בדיוק כמו ב-JavaScript: switch (value) { case "a": ...; break; default: ... }. ה-cases מושווים עם ===. TypeScript מוסיף בדיקות: ערך case שאף פעם לא יכול להתאים לטיפוס שעליו עושים switch הוא שגיאה (TS2678), ובתוך כל case המשתנה מצומצם ל-case הזה.
איך הופכים switch לממצה ב-TypeScript?
הוסיפו default שמשים את הערך למשתנה מטיפוס never: default: { const unreachable: never = value; throw new Error(...) }. כשכל איברי ה-union מטופלים, הערך שם הוא never והקוד מתקמפל. כשאחד חסר, הקומפיילר מדווח על האיבר החסר (TS2322).
איך מטפלים בכמה cases עם אותו קוד ב-switch של TypeScript?
ערמו את התוויות בלי קוד ביניהן: case "sat": case "sun": return "weekend";. cases ריקים נופלים ל-case הבא. האפשרות noFallthroughCasesInSwitch מדווחת רק על cases שיש בהם קוד ואין בהם break או return, כך שתוויות מוערמות נשארות מותרות.
האם switch (true) מצמצם טיפוסים ב-TypeScript?
כן, מאז TypeScript 5.3. ב-switch (true) { case typeof x === "string": ... }, x מצומצם ל-string בתוך ה-case הזה, בדיוק כמו שהיה ב-if. זו חלופה קריאה לשרשרת של if/else if עם בדיקות של טווחים או טיפוסים.