5.4 פונקציות וצמצום טיפוסים תרגול
תרגול - פונקציות וצמצום טיפוסים¶
תרגיל 1 - פונקציות מוטייפות¶
א. כתבו פונקציה clamp שמקבלת שלושה מספרים: value, min, max, ומחזירה את הערך מוגבל לטווח. אם הערך קטן מ-min, מחזירה min. אם גדול מ-max, מחזירה max. אחרת מחזירה את הערך עצמו.
ב. כתבו פונקציה repeatString שמקבלת מחרוזת ומספר אופציונלי times (ברירת מחדל 2), ומחזירה את המחרוזת חוזרת על עצמה.
ג. כתבו פונקציה joinStrings שמקבלת separator (מחרוזת) ואחריו מספר בלתי מוגבל של מחרוזות (rest parameter), ומחזירה את כולן מחוברות עם ה-separator.
joinStrings(", ", "Alice", "Bob", "Charlie"); // "Alice, Bob, Charlie"
joinStrings(" - ", "a", "b"); // "a - b"
תרגיל 2 - טיפוסים של פונקציות¶
א. הגדירו type בשם MathOperation שהוא פונקציה שמקבלת שני מספרים ומחזירה מספר.
ב. צרו ארבע פונקציות מהטיפוס הזה: add, subtract, multiply, divide.
ג. כתבו פונקציה calculate שמקבלת שני מספרים ו-MathOperation, ומחזירה את התוצאה. טפלו בחלוקה באפס (החזירו null אם מנסים לחלק באפס).
ד. כתבו פונקציה applyAll שמקבלת מספר ומערך של MathOperation, ומפעילה את כל הפעולות בזו אחר זו (התוצאה של כל פעולה מועברת כפרמטר ראשון לפעולה הבאה, הפרמטר השני תמיד 0).
תרגיל 3 - typeof narrowing¶
כתבו פונקציה stringify שמקבלת value: string | number | boolean | null | undefined ומחזירה מחרוזת:
string- מחזירה בגרשיים:'"hello"'number- מחזירה עם n ספרות אחרי הנקודה:"3.14"boolean- מחזירה"true"או"false"null- מחזירה"null"undefined- מחזירה"undefined"
השתמשו ב-typeof לצמצום.
תרגיל 4 - instanceof narrowing¶
הגדירו שלוש classes:
class ValidationError {
constructor(public field: string, public message: string) {}
}
class NetworkError {
constructor(public url: string, public statusCode: number) {}
}
class TimeoutError {
constructor(public url: string, public timeoutMs: number) {}
}
א. כתבו פונקציה handleError שמקבלת error: ValidationError | NetworkError | TimeoutError ומחזירה הודעת שגיאה מתאימה לכל סוג:
- ValidationError: "Validation failed for field 'X': message"
- NetworkError: "Network error (status) fetching url"
- TimeoutError: "Request to url timed out after Xms"
ב. כתבו פונקציה isRetryable שמקבלת את אותו union ומחזירה boolean. רק NetworkError (עם statusCode >= 500) ו-TimeoutError ניתנים ל-retry.
תרגיל 5 - discriminated unions¶
הגדירו discriminated union לייצוג תגובות מ-API:
// Success response - has status "success", data (any type), and optional message
// Error response - has status "error", errorCode (number), and errorMessage (string)
// Loading response - has status "loading", and optional progress (number 0-100)
א. הגדירו את הטיפוסים ואת ה-union type ApiResponse.
ב. כתבו פונקציה renderResponse שמקבלת ApiResponse ומחזירה מחרוזת HTML מתאימה לכל מצב:
- success: "<div class='success'>Data: ...</div>"
- error: "<div class='error'>Error CODE: message</div>"
- loading: "<div class='loading'>Loading... X%</div>" (אם אין progress, לא מציגים אחוזים)
ג. הוסיפו מקרה רביעי: status: "idle" (ללא שדות נוספים). ודאו עם exhaustive checking ש-renderResponse מטפלת בכל המקרים.
תרגיל 6 - type predicates¶
א. כתבו type predicate isString שבודק אם ערך מסוג unknown הוא מחרוזת.
ב. כתבו type predicate isNonEmptyArray שבודק אם ערך מסוג unknown הוא מערך עם לפחות איבר אחד. הטיפוס המוחזר: value is unknown[].
ג. הגדירו אינטרפייס AdminUser שיורש מ-User (עם name ו-email) ומוסיף permissions: string[]. כתבו type predicate isAdmin שבודק אם User | AdminUser הוא AdminUser.
ד. נתון מערך מעורב:
let data: (string | number | null | undefined)[] = ["hello", 42, null, "world", undefined, 7, null];
השתמשו ב-type predicates ו-filter כדי לקבל:
- מערך של מחרוזות בלבד
- מערך של מספרים בלבד
- מערך ללא null ו-undefined
תרגיל 7 - שילוב הכל - מערכת אירועים¶
בנו מערכת אירועים פשוטה (event system) עם הטיפוסים הבאים:
// define these event types as a discriminated union:
// - "click" event with x: number, y: number
// - "keypress" event with key: string, ctrlKey: boolean
// - "scroll" event with scrollTop: number, scrollLeft: number
// - "resize" event with width: number, height: number
א. הגדירו את ה-discriminated union AppEvent.
ב. הגדירו type EventHandler שהוא פונקציה שמקבלת AppEvent ומחזירה void.
ג. כתבו פונקציה describeEvent שמקבלת AppEvent ומחזירה תיאור טקסטואלי של האירוע. השתמשו ב-exhaustive checking.
ד. כתבו פונקציה filterEvents שמקבלת מערך של AppEvent ומחרוזת eventType, ומחזירה רק את האירועים מהסוג המבוקש. השתמשו ב-type predicate.