ניתוח סטטי

ניתוח סטטי הוא סוג של בדיקה שמאפשרת בדיקה אוטומטית של הקוד, בלי להריץ אותו בפועל ובלי לכתוב בדיקה אוטומטית. סביר להניח שכבר ראיתם בדיקות כאלה אם אתם משתמשים בסביבת פיתוח משולבת (IDE) כמו VSCode – בדיקת הסוג שמבוצעת על ידי TypeScript היא סוג של ניתוח סטטי, והיא יכולה להופיע כשורות מעוותות בשגיאות או באזהרות.

ESLint

ESLint הוא כלי שיכול לתת משוב על בעיות אפשריות ב-codebase. יכול להיות שהבעיות האלה הן בטוחות,אבל שגיאות או התנהגות לא רגילה מעצמו. ב-ESLint אפשר להחיל מספר כללים שנבדקים ב-codebase, כולל רבים בקבוצה "Recommended" (מומלץ).

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

  try {
    const result = await complexFetchFromNetwork();
    if (!result.ok) {
      throw new Error("failed to fetch");
    }
  } finally {
    // warning - this will 'overrule' the previous exception!
    return false;
  }

לכן, ESLint הוא לא תחליף לתהליך בדיקה תקין (וגם מדריך סגנון שמגדיר איך צריך להיראות קוד בסיס), כי הוא לא יממש את כל הגישה הלא-אורתודוקסית שמפתח ינסה ליישם ב-codebase שלכם. המדריך של Google לשיטות הנדסה כולל קטע קצר בנושא שמירה על פשטות.

ב-ESLint אפשר לשבור כלל ולהוסיף הערות לקוד כ "מותר". לדוגמה, אפשר לאפשר את הלוגיקה הקודמת על ידי רישום שלה באופן הבא:

  finally {
    // eslint-disable-next-line no-unsafe-finally
    return false;
  }

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

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

יישומי פלאגין של ESLint לתמיכה בדפדפן

אפשר להוסיף ל-ESLint פלאגין שמסמן את השימוש בממשקי API שלא נתמכים בהרבה אנשים, או שלא נתמכים על ידי רשימת דפדפני היעד. בחבילה eslint-plugin-compat מוצגת אזהרה כשממשק API לא זמין למשתמשים, כך שלא צריך לעקוב כל הזמן אחרי הנתונים בעצמם.

בדיקת סוגים לניתוח סטטי

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

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

TypeScript

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

לדוגמה, הקוד הבא, שצפוי לקבל קריאה חוזרת (callback) עם קבלת שם של string וגיל number:

const callback = (name: string, age: string): void => {
  console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);

יוצר את השגיאה הבאה בהרצה באמצעות TypeScript, או גם כשמעבירים את העכבר מעל סביבת הפיתוח המשולבת (IDE):

bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
  Types of parameters 'age' and 'age' are incompatible.
    Type 'number' is not assignable to type 'string'.

4 onBirthday(callback);
             ~~~~~~~~

Found 1 error in bad.ts:4
הקוד מהדוגמה הקודמת, שמוצג בסביבת פיתוח משולבת (IDE) והודעת השגיאה מופיעה בחלון קופץ.
VSCode מציין שהעברת סוג שגוי.

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

החלק המאתגר ביותר בשימוש ב-TypeScript הוא הגדרה נכונה שלו. לכל פרויקט צריך קובץ tsconfig.json, שלמרות שהוא משמש בעיקר את כלי שורת הפקודה tsc עצמו, סביבות פיתוח משולבות (IDE) כמו VSCode קוראות גם הרבה כלי פיתוח וכלים אחרים, כולל Vitest. בקובץ יש מאות אפשרויות ודגלים, ואפשר למצוא כאן כמה משאבים טובים להגדרה:

טיפים כלליים ל-TypeScript

כשמגדירים שימוש ב-TypeScript בקובץ tsconfig.json, חשוב לזכור את הנקודות הבאות:

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

TypeScript משתמע מסוג כלשהו

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

הסימון יגרום לפונקציה הזו להחזיר שגיאה:

export function fibonacci(n) {
  if (n <= 1) {
    return 0;
  } else if (n === 2) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

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

function fibonacci(n: any): any

הקריאות לפונקציה הזו יוכלו להעביר ערך מסוג any (סוג שמאפשר כל סוג אחר), ולא רק number. כשמפעילים את הדגל noImplicitAny, אפשר להגן על קוד מהסוג הזה במהלך הפיתוח, בלי לכתוב בדיקות לוגיקה עסקיות מקיפות כדי שהקוד יעביר סוגי נתונים שגויים במקומות ספציפיים.

התיקון הפשוט כאן הוא לסמן גם את הארגומנט n וגם את סוג ההחזרה של fibonacci כ-number.

הדגל noImplicitAny לא מונע בצורה מפורשת לכתוב את any ב-codebase. עדיין אפשר לכתוב פונקציה שמקבלת או מחזירה את הסוג any. הוא רק מבטיח שתיתן לכל משתנה סוג.