שגיאת טיפוס יכולה להיראות כמו מכשול כשמנסים לסיים תוכנית. היא גם משוב מוקדם על טעות. נראה מה בודק טיפוסים עושה, איך מריצים אותו ב-Python וב-TypeScript, איך הוא עוזר לסוכן לעדכן את הקריאות לפונקציה, ואילו שגיאות עדיין דורשות טסטים.
הדוגמאות בסרטון הזה הן ב-Python. אותם רעיונות תקפים גם בשפות אחרות, ונראה גם איך בודקים TypeScript. הנה מודול חיוב קטן. הפונקציה total מקבלת רשימה של מחירים ומחברת אותם. במקום אחר, מישהו קורא לה עם מחיר בודד במקום עם רשימה. ב-Python הטיפוסים הם דינמיים, כלומר הטיפוסים של הערכים נבדקים בזמן שהתוכנית רצה. גם JavaScript, Ruby ושפות רבות אחרות עובדות כך. אז כשמריצים את הקובץ הזה עם Python, שום דבר לא מתלונן מראש על הקריאה הזאת. היא נכשלת בפעם הראשונה שהשורה רצה, וזה בהחלט יכול לקרות בפרודקשן. עכשיו נריץ בודק טיפוסים סטטי על אותו קוד Python עם האנוטציות. הוא קורא את הקריאה עוד לפני שהתוכנית רצה, רואה שמספר בודד הוא לא רשימה של מספרים, ומדווח על שגיאה. בשלב הזה שום דבר עוד לא רץ. בשפה עם טיפוסים סטטיים, כמו Java, הבדיקה הזאת היא חלק מהקומפילציה של התוכנית. Python בודקת את הפעולה הזאת כשהיא מתבצעת. הוספה של בודק טיפוסים סטטי מאפשרת לכם גם לזהות את אי-ההתאמה לפני שמריצים את התוכנית.
בודק הטיפוסים הוא אחת מכמה בדיקות שנותנות משוב על שינוי. אחד ההבדלים ביניהן הוא כמה זמן לוקח לכל אחת לענות. בודק טיפוסים מנתח את הקוד בלי להריץ את האפליקציה. בפרויקט קטן או בהרצה אינקרמנטלית, הוא יכול לדווח על אי-התאמות בפחות משנייה. מערך טסטים מריץ את הקוד כדי לבדוק התנהגויות מסוימות. סט קטן עשוי לקחת שניות, וסט גדול יותר יכול לקחת דקות. משוב מהיר מאפשר לסוכן למצוא ולתקן טעויות כל עוד השינוי הרלוונטי עדיין קטן. בדיקה של שנייה קל להריץ אחרי כל עריכה, וטיפוסים, טסטים מהירים ולינטרים יכולים כולם לתרום ללולאה הפנימית הזאת. אבל מהירות היא לא היתרון העיקרי של בודק טיפוסים. בפרויקט גדול, הרצה מלאה של בדיקת טיפוסים יכולה לקחת יותר מכמה טסטים מהירים. מה שהבודק מוסיף הוא כיסוי. הוא בוחן כל קריאה בקוד הנבדק, כולל קריאות במסלולים שאף טסט לא מריץ.
ב-Python מקבלים בדיקה סטטית דרך טיפוסים הדרגתיים. טיפוסים הדרגתיים אומר שאפשר להשתמש בקוד עם טיפוסים ובקוד בלי טיפוסים באותה תוכנית, כך שמוסיפים טיפוסים לחלקים מסוימים והשאר נשאר בלי. ב-Python, הטיפוסים האלה נכתבים כאנוטציות. כאן לפרמטר prices יש אנוטציה של רשימת floats. Python לא אוכפת את אנוטציות הטיפוס האלה כשקוראים לפונקציה. מספר בודד שמועבר לפונקציה עדיין מגיע אליה, ושם החיבור נכשל. בודק הטיפוסים הנפרד מנתח את הקוד ואת האנוטציות שלו. הוא יכול לעקוב אחרי הטיפוסים דרך קריאות לפונקציות בלי להריץ את הקריאות האלה. אפשר לאמץ את הבדיקה קובץ אחרי קובץ. כברירת מחדל, mypy מדלג על גופים של פונקציות בלי אנוטציות. מצב strict בודק את הגופים האלה וגם מדווח על אנוטציות חסרות. הוספת אנוטציות נותנת לו טיפוסים מדויקים יותר לבדוק. TypeScript מוסיפה באופן דומה בדיקה סטטית ל-JavaScript. אנוטציות הטיפוס שלה מוסרות כשנוצר קוד JavaScript.
ב-Python, הריצו mypy --strict עם נקודה בסוף. קודם צריך להתקין את mypy בסביבה של הפרויקט, למשל כתלות פיתוח. הנקודה אומרת ל-mypy לאתר קובצי Python מתחת לתיקייה הנוכחית, וההחרגות עדיין חלות. mypy מדווח על שימושים לא תואמים בקוד שהוא בודק. מצב strict מתאים לפרויקט שכבר יש בו אנוטציות, כמו מודול החיוב הזה. ב-TypeScript, הריצו npx tsc --no-emit מתוך פרויקט ש-TypeScript מותקנת ומוגדרת בו. הדגל --no-emit בודק את הפרויקט המוגדר בלי לכתוב JavaScript. רמת הקפדנות היא הגדרה נפרדת בקובץ ההגדרות הזה. שגיאה נראית ככה. קובץ, מספר שורה, איזה ארגומנט שגוי, איזה טיפוס היה לו, ואיזה טיפוס היה צפוי. זה משוב שימושי לסוכן. הוא אומר מה כן היה מתאים. שתי הפקודות מנתחות את קובצי הפרויקט שנבחרו, בלי להריץ את האפליקציה. זה מאפשר להן לדווח על אי-התאמה גם במסלול שמעולם לא הפעלתם בטסט.
נניח שהסוכן משנה חתימה של פונקציה במהלך ריפקטורינג. כאן total מקבלת פרמטר שני, שיעור המס. כל קריאה קיימת שמעבירה רק את המחירים כבר לא מתאימה לחתימה החדשה. בודק הטיפוסים מדווח על הקריאות לא תואמות בכל הקוד הנבדק, במעבר אחד. כאן הוא מוצא שתיים, אחת במודול העגלה ואחת במודול החשבונית. כל הודעה מציינת את הקובץ, את השורה ואת הארגומנט החסר. הסוכן מקבל רשימה של מקומות לעדכן, בלי להריץ אף אחת מהקריאות האלה. הסוכן מוסיף שיעור מס לקריאה במודול העגלה ומריץ שוב את הבודק. נשארת שגיאה אחת, והיא מצביעה על הקריאה שעדיין צריכה את אותו שינוי. בלי בדיקה סטטית, אי-התאמה עלולה להתגלות רק כשטסט או משתמש מריצים את המסלול הזה. קריאות שאף פעם לא מריצים יכולות להישאר בלי שיתגלו.
אנוטציות גם מתעדות מידע עבור מי שקורא את הקוד. ה-docstring אומר ש-prices הוא רשימה של floats, אבל שום דבר לא בודק את הטקסט הזה כשהפונקציה משתנה. האנוטציה מציינת את הטיפוס הצפוי בצורה שהבודק יודע להשתמש בה. פעולה לא תואמת בקוד שנבדק מייצרת שגיאה, במקום להשאיר רק משפט שכבר לא נכון. נניח ש-total משתנה כך שהיא מחזירה את הסכום כטקסט מעוצב, והאנוטציה שלה אומרת עכשיו שהיא מחזירה מחרוזת. קריאה שעדיין מכפילה את הסכום בשיעור מס מקבלת שגיאה בהרצה הבאה של בדיקת הטיפוסים. אם טיפוס ההחזרה היה מתואר רק ב-docstring, אותו שינוי לא היה מייצר שום הודעה. חתימה היא תיעוד שנבדק בכל הרצה של בדיקת טיפוסים. בתוך הקוד הנבדק, שימושים לא תואמים מייצרים כשלים ש-docstring רגיל לא מייצר.
האנוטציות של Python יכולות לעשות יותר מלומר float או string. הן יכולות גם לתת לערך שם שאומר מה הוא מייצג. קואורדינטת x וקואורדינטת y הן שתיהן float, אבל להחליף ביניהן זה באג אמיתי. NewType יוצר טיפוס נפרד לכל אחת מהן. בזמן ריצה כל אחת היא עדיין float רגיל. אבל בודק הטיפוסים מתייחס ל-X ול-Y כטיפוסים שונים. אז כשקריאה מעבירה את y במקום שבו צריך x, mypy מדווח על זה, למרות ששני הערכים הם float. אותו דבר עובד למזהה לקוח ולמזהה הזמנה, ששניהם מספרים שלמים. כינוי טיפוס נותן שם לטיפוס גדול יותר. כאן משבצת היא זוג מספרים, ולוח שחמט הוא מילון ממשבצות לכלים. עם השמות האלה, החתימה אומרת שהפונקציה piece_at מקבלת לוח ומשבצת. היא מחזירה כלי, או None כשהמשבצת ריקה. הקו האנכי יוצר union, ערך שיכול להיות מטיפוס אחד או מהשני. מי שעובד על הקוד הזה מדבר על לוחות ועל משבצות, לא על מילונים של זוגות. השמות מאפשרים לקוד לדבר באותן מילים. הקורא רואה board ו-square, ולא צריך לפענח בעצמו שמילון של זוגות הוא בעצם לוח שחמט. אז טיפוסים עם שם מתעדים את הכוונה של מי שכתב את הקוד. הם אומרים לקורא, וגם לסוכן, מה כל ערך מייצג, ובודק הטיפוסים שומר על הקוד עקבי עם הכוונה הזו.
משוב על טיפוסים הוא גם סיבה לבחור בשפה עם טיפוסים כשעובדים עם סוכנים. מחקרים על מודלים שכותבים TypeScript מצאו שרוב שגיאות הקומפילציה שלהם היו שגיאות טיפוס. המחקרים האלה בדקו קוד שמודל כתב בבת אחת, לפני שהריץ בודק כלשהו. סוכן שמריץ את הבודק זוכה לראות את השגיאות האלה ולתקן אותן עוד לפני שאתם נתקלים בהן. אפשרות אחרת היא להתחיל מלכתחילה בשפה עם טיפוסים. GitHub דיווחה ש-TypeScript הפכה אצלה לשפה שהכי הרבה תורמים חודשיים השתמשו בה, באוגוסט 2025. הדוח הזה מודד פופולריות, לא את הסיבות לה. משוב סטטי הוא אחת הסיבות לכך ששפה עם טיפוסים שימושית כשעובדים עם סוכנים. אז בודק טיפוסים תופס את רוב שגיאות הקומפילציה שמודלים עושים כשהם כותבים קוד עם טיפוסים. הוא נותן לסוכן משוב קונקרטי כדי לתקן את השגיאות האלה, בלי לבקש ממודל אחר לשפוט את הקוד.
דוגמת החיוב מראה גם מה טיפוסים מפספסים. נתחיל מהחוזה. הפונקציה price after discount מקבלת מחיר ואחוז, והיא צריכה להחזיר את המחיר הסופי אחרי הנחה באחוז הזה. הנה המימוש שלה. ננסה אותה עם מחיר של מאה והנחה של עשרים אחוז. צריך לצאת שמונים. המימוש הזה מחזיר עשרים, שזה גובה ההנחה ולא המחיר אחרי ההנחה. mypy במצב strict מרוצה מזה לגמרי. שני הארגומנטים הם floats, הערך המוחזר הוא float, וכל קריאה שמתייחסת לתוצאה כמחיר הסופי מקבלת מספר שגוי. אז טיפוסים בודקים שמשתמשים בערכים בצורה תואמת. האם ערך הוא הערך הנכון, זה התפקיד של טסט. לכן בדיקות טיפוסים וטסטים של התנהגות משלימים זה את זה.
אז תנו לבודק הטיפוסים לעבור ראשון. הוא תופס את הבלבולים תוך שניות, ולטסטים נשאר לבדוק שהתשובות נכונות. תודה שצפיתם, ונתראה בסרטון הבא.