שיעורי מודול (1/2)
סוג שומרים
צמצום סוג הוא אחד המושגים החשובים ביותר ב-TypeScript. עם זאת, לעתים קרובות, מגנים מסוג סטנדרטי כמו typeof או instanceof אינם מספיקים עבור אובייקטים מותאמים אישית מורכבים. כאן נכנסים לתמונה מגני סוג מותאם אישית.
מגנים מסוג סטנדרטי
נתחיל בסיכום כיצד TypeScript מצמצם סוגים באמצעות אופרטורים סטנדרטיים של JavaScript:
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 יידע שהפרמטר שעבר הוא מהסוג שצוין.
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 על סוג המשתנה בפועל:
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: שומר סוג מיתר
צור פונקציה פשוטה בשם isString שפועלת כשומר סוג מותאם אישית כדי לוודא אם ערך לא ידוע הוא מחרוזת.
הצג רמז
סוג ההחזר של הפונקציה חייב להיות val is string, ואתה צריך להשתמש ב-typeof כדי לבדוק אם הוא שווה ל'string'.
הפתרון זמין לאחר 3 ניסיונות
תרגיל 2: Premium User Type Guard
בהתחשב בסוגי User ו-PremiumUser, כתוב פונקציית שמירה על סוג הואPremiumUser(משתמש: משתמש): המשתמש הוא PremiumUser שבודק אם למשתמש יש את התפקיד 'פרימיום'.
הצג רמז
הגדר את החתימה כפונקציה isPremiumUser(משתמש: משתמש): המשתמש הוא PremiumUser והשווה את user.role עם 'premium'.
הפתרון זמין לאחר 3 ניסיונות
תרגיל 3: אימות אובייקט שגיאה מותאם אישית
הטמיע את הפונקציה isCustomError(err: unknown): err היא פונקציה CustomError המאמתת אם ערך לא ידוע הוא אובייקט CustomError שאינו ריק המכיל את מפתח 'קוד'.
הצג רמז
תחילה בדוק אם סוג השגיאה הוא 'אובייקט' ולא null, ולאחר מכן השתמש באופרטור 'in' כדי לבדוק את המאפיין 'קוד'.
הפתרון זמין לאחר 3 ניסיונות
תרגיל 4: Admin Type Guard
בהינתן שני ממשקים User (עם תפקיד מאפיין: מחרוזת) ו-Admin (הרחבת משתמש ובעלת מאפיין adminToken: מחרוזת), כתוב פונקציית שמירה של סוג בשם isAdmin שמקבלת משתמש מסוג User ומחזירה למשתמש פרדיקט של סוג הוא Admin. על השומר לבדוק אם תפקיד המשתמש שווה ל'אדמין'.
הצג רמז
הגדר את החתימה כפונקציה isAdmin(משתמש: משתמש): המשתמש הוא Admin ובדוק אם user.role === 'admin'.
הפתרון זמין לאחר 3 ניסיונות