איך בוחרים בין הגיוני למועיל?

02/05/2024

הטיפוס object ב TypeScript נכנס לשפה בגירסה 2.2 של טייפסקריפט כדי לפתור בעיה. באותו זמן דפדפנים כללו את הפונקציה Object.create שיוצרת אובייקט חדש שהפרוטוטייפ שלו הוא הפרמטר שקיבלה, אבל הפרמטר ש create יכלה לקבל היה חייב להיות משהו שאינו "פרימיטיב" כלומר משהו שאפשר להוסיף לו מפתחות, לדוגמה מערך, פונקציה או אוביקט.

אז עכשיו אנחנו יכולים להגדיר את הטיפוס:

create(o: object | null): any;

ורגע אם כבר הגדרנו את create אפשר להמשיך לרוץ עם אותו רעיון ולהגדיר גם את:

setPrototypeOf(o: any, proto: object | null): any;

ויש עוד כמה הגדרות שאפשר למצוא ב es5.d.ts שהמשותף לכולן הוא ה object | null. בעצם יש רק מקום אחד ש object מופיע בלי החיבור ל null וזה הטיפוס של הפונקציה Object.keys:

keys(o: object): string[];

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

בחזרה לאתגר שלנו - למה null הוא לא חלק מ object? למה להגדיר טיפוס חדש כשכל פעם שמשתמשים בו זה כחלק מהחיבור object | null?

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

typeof null === 'object'

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