• בלוג
  • עמוד 10
  • בסקאלה זה לא היה קורה (או: מה חדש בטייפסקריפט 5.4)

בסקאלה זה לא היה קורה (או: מה חדש בטייפסקריפט 5.4)

01/02/2024

השינוי הראשון ברשימת החידושים של טייפסקריפט 5.4 הוא שטייפסקריפט תתחיל לשמור מסקנות על טיפוסים לתוך Closures, או בדוגמה, הקוד הבא כבר יתקמפל בלי שגיאות:

function getUrls(url: string | URL, names: string[]) {
    if (typeof url === "string") {
        url = new URL(url);
    }

    return names.map(name => {
        url.searchParams.set("name", name)
        //  ~~~~~~~~~~~~
        // error!
        // Property 'searchParams' does not exist on type 'string | URL'.

        return url.toString();
    });
}

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

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

החל מגירסה 5.4 הקוד הזה יתחיל לעבוד בלי בעיה, שזה אחלה. אבל השאלה האמיתית היא האם ההמרה מ String ל URL בכלל צריכה להיות חלק מהפונקציה. עכשיו אני יודע TypeScript לא מחפשת להגיד לאנשים מה לעשות והמטרה היא לאפשר בדיקת טיפוסים שתעבוד על קוד שאנשי JavaScript היו שמחים לכתוב. ובכל זאת מעניין לשים לב לתבנית מקבילה בסקאלה לטיפול באותה בעיה. בסקאלה הגישה היא שהמרה מ String ל URL היא "יכולת" של ה String ולא של הפונקציה, או יותר נכון יכולת של String בתוך קובץ או מודול מסוים. בשביל שזה יעבוד אני מגדיר שם פונקציית המרה שנראית כך:

  implicit def stringToURL(url: String): URL =
    new URI(url).toURL

ואם אותה פונקציה נמצאת ב Scope אז אני יכול לכתוב פונקציה שמצפה לקבל URL ולהפעיל אותה עם String והכל פשוט יעבוד:

  def printHost(url: URL): Unit =
    println(url.getHost)

  @main
  def demo(): Unit =
    val url: String = "https://www.tocode.co.il"
    printHost(url)

הקומפיילר מפעיל באופן אוטומטי את פונקציית ההמרה ובעצם הפונקציה נקראת עם אוביקט מסוג URL.

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