דילוג לתוכן המרכזי
מודול 5 · שיעור 1 מתוך 29/14 בקורס~15 min
שיעורי מודול (1/2)

סוג שומרים

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

מגנים מסוג סטנדרטי

נתחיל בסיכום כיצד TypeScript מצמצם סוגים באמצעות אופרטורים סטנדרטיים של JavaScript:

TS
function processInput(val: string | number) {
  if (typeof val === 'string') {
    // Here 'val' is of type string
    console.log(val.toUpperCase());
  } else {
    // Here 'val' is of type number
    console.log(val.toFixed(2));
  }
}

מגנים מסוג מותאם אישית (מפעיל is)

כדי להגדיר משמר סוג מותאם אישית, אנו יוצרים פונקציה שמחזירה פרדיקט סוג בפורמט parameterName is Type במקום סוג החזרה בוליאני סטנדרטי.

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

TS
interface Cat {
  name: string;
  meow(): void;
}

interface Dog {
  name: string;
  bark(): void;
}

// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function makeNoise(pet: Cat | Dog) {
  if (isCat(pet)) {
    // Here TypeScript knows 'pet' is a Cat
    pet.meow();
  } else {
    // Here TypeScript knows 'pet' is a Dog
    pet.bark();
  }
}

בטיחות והטלה (as לעומת מגני סוג)

יציקת סוגים (לדוגמה, val as Cat) מאלצת את המהדר לסמוך על המפתח ללא כל אימות בזמן ריצה אמיתי. אם אובייקט זמן הריצה לא יעמוד בציפיות, הקוד ייכשל בשקט או יזרוק חריגים.

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

TS
function processInput(input: unknown) {
  // unsafe casting: could crash if input does not have the split method
  // const str = input as string;
  // console.log(str.split(' '));

  // safe guard
  if (isString(input)) {
    console.log(input.split(' ')); // 100% Safe!
  }
}

נסה זאת בעצמך

תרגיל 1: שומר סוג מיתר

פעילות גופנית#ts.m5.l1.e1
ניסיונות: 0טוען...

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

טוען עורך...
הצג רמז

סוג ההחזר של הפונקציה חייב להיות val is string, ואתה צריך להשתמש ב-typeof כדי לבדוק אם הוא שווה ל'string'.

הפתרון זמין לאחר 3 ניסיונות

תרגיל 2: Premium User Type Guard

פעילות גופנית#ts.m5.l1.e2
ניסיונות: 0טוען...

בהתחשב בסוגי User ו-PremiumUser, כתוב פונקציית שמירה על סוג הואPremiumUser(משתמש: משתמש): המשתמש הוא PremiumUser שבודק אם למשתמש יש את התפקיד 'פרימיום'.

טוען עורך...
הצג רמז

הגדר את החתימה כפונקציה isPremiumUser(משתמש: משתמש): המשתמש הוא PremiumUser והשווה את user.role עם 'premium'.

הפתרון זמין לאחר 3 ניסיונות

תרגיל 3: אימות אובייקט שגיאה מותאם אישית

פעילות גופנית#ts.m5.l1.e3
ניסיונות: 0טוען...

הטמיע את הפונקציה isCustomError(err: unknown): err היא פונקציה CustomError המאמתת אם ערך לא ידוע הוא אובייקט CustomError שאינו ריק המכיל את מפתח 'קוד'.

טוען עורך...
הצג רמז

תחילה בדוק אם סוג השגיאה הוא 'אובייקט' ולא null, ולאחר מכן השתמש באופרטור 'in' כדי לבדוק את המאפיין 'קוד'.

הפתרון זמין לאחר 3 ניסיונות

תרגיל 4: Admin Type Guard

פעילות גופנית#ts.m5.l1.e4
ניסיונות: 0טוען...

בהינתן שני ממשקים User (עם תפקיד מאפיין: מחרוזת) ו-Admin (הרחבת משתמש ובעלת מאפיין adminToken: מחרוזת), כתוב פונקציית שמירה של סוג בשם isAdmin שמקבלת משתמש מסוג User ומחזירה למשתמש פרדיקט של סוג הוא Admin. על השומר לבדוק אם תפקיד המשתמש שווה ל'אדמין'.

טוען עורך...
הצג רמז

הגדר את החתימה כפונקציה isAdmin(משתמש: משתמש): המשתמש הוא Admin ובדוק אם user.role === 'admin'.

הפתרון זמין לאחר 3 ניסיונות