5.2 טיפוסים בסיסיים תרגול
תרגול - טיפוסים בסיסיים¶
תרגיל 1 - אנוטציות בסיסיות¶
הוסיפו type annotations מתאימים לכל המשתנים הבאים. אל תשנו את הערכים - רק הוסיפו טיפוסים:
let city = "Tel Aviv";
let population = 460613;
let isCapital = false;
let coordinates = [32.0853, 34.7818];
let info = { name: "Tel Aviv", country: "Israel", founded: 1909 };
let mayor = null;
let nickname = undefined;
עכשיו ענו: באילו מקרים ה-type annotation באמת הכרחי, ובאילו TS מסיקה נכון לבד?
תרגיל 2 - טאפלים¶
א. הגדירו טאפל coordinate שמכיל שני מספרים (קו רוחב וקו אורך). אתחלו אותו עם הערכים [32.0853, 34.7818].
ב. הגדירו טאפל httpResponse שמכיל מספר (status code), מחרוזת (status text), ובוליאני (success). אתחלו אותו עם [200, "OK", true].
ג. כתבו פונקציה parseEntry שמקבלת מחרוזת בפורמט "name:age" (למשל "Alice:30") ומחזירה טאפל [string, number] עם השם והגיל.
ד. מה קורה אם מנסים להוסיף איבר לטאפל עם push? נסו ובדקו.
תרגיל 3 - enums ו-as const¶
א. צרו enum בשם LogLevel עם הערכים: Debug, Info, Warning, Error, Critical. הערך של Debug צריך להיות 0 (ברירת מחדל).
ב. צרו string enum בשם HttpMethod עם הערכים: Get = "GET", Post = "POST", Put = "PUT", Delete = "DELETE".
ג. עכשיו צרו את אותו דבר בדיוק עם as const במקום enum (גם ל-LogLevel וגם ל-HttpMethod). צרו גם את הטיפוס המתאים עם typeof.
ד. כתבו פונקציה getMethodColor שמקבלת HttpMethod ומחזירה צבע כמחרוזת: GET ירוק, POST כחול, PUT כתום, DELETE אדום.
תרגיל 4 - any לעומת unknown¶
הקוד הבא משתמש ב-any. שכתבו אותו כך שישתמש ב-unknown במקום, והוסיפו את הבדיקות הנדרשות:
function processValue(value: any): string {
if (typeof value === "number") {
return value.toFixed(2);
}
return value.toUpperCase();
}
function getLength(value: any): number {
return value.length;
}
function callIfFunction(value: any): void {
value();
}
תרגיל 5 - null ו-undefined¶
א. כתבו פונקציה findUser שמקבלת מערך של שמות (string[]) ושם לחיפוש (string), ומחזירה את השם אם נמצא או null אם לא:
findUser(["Alice", "Bob", "Charlie"], "Bob"); // "Bob"
findUser(["Alice", "Bob", "Charlie"], "David"); // null
ב. כתבו פונקציה formatUser שמקבלת אובייקט עם name: string ו-email אופציונלי (string | undefined), ומחזירה מחרוזת מפורמטת:
formatUser({ name: "Alice", email: "alice@example.com" }); // "Alice (alice@example.com)"
formatUser({ name: "Bob" }); // "Bob (no email)"
ג. כתבו פונקציה safeParseInt שמקבלת string | null | undefined ומחזירה number | null. אם הקלט הוא null, undefined, או מחרוזת שלא ניתנת להמרה - מחזירה null.
תרגיל 6 - הסקת טיפוסים ו-literal types¶
א. לכל אחד מהמקרים הבאים, כתבו מה הטיפוס שטייפסקריפט תסיק (בלי להריץ - רק חישבו). אחר כך בדקו ב-IDE:
const name = "Alice";
let name2 = "Alice";
const age = 30;
let age2 = 30;
const isAdmin = true;
const coords = [1, 2] as const;
let coords2 = [1, 2];
const config = { debug: true, version: "1.0" };
const config2 = { debug: true, version: "1.0" } as const;
ב. הסבירו: למה const x = "hello" מקבל טיפוס "hello" אבל const arr = [1, 2, 3] מקבל טיפוס number[] ולא [1, 2, 3]?
ג. כתבו טיפוס Season שהוא union של ארבע מחרוזות ליטרליות: "spring", "summer", "autumn", "winter". כתבו פונקציה getTemperature שמקבלת Season ומחזירה מספר (טמפרטורה ממוצעת).
תרגיל 7 - אנוטציות על אובייקטים¶
א. הגדירו משתנה student עם הטיפוס הבא (inline, בלי interface):
- name: מחרוזת
- age: מספר
- grades: מערך של מספרים
- address: אובייקט עם city (מחרוזת) ו-street (מחרוזת)
- graduated: בוליאני אופציונלי
אתחלו אותו עם ערכים לבחירתכם.
ב. הגדירו משתנה readonlyPoint שהוא אובייקט readonly עם x ו-y מספריים. נסו לשנות ערך ובדקו שאתם מקבלים שגיאה.
ג. למה הגישה של אנוטציות inline לא נוחה? מה הבעיה כשיש שני משתנים מאותו טיפוס?
תרגיל 8 - תרגום מפייתון¶
תרגמו את הקוד הבא מפייתון לטייפסקריפט. שימו לב לכל ההבדלים בטיפוסים:
from typing import Optional
from enum import Enum
class Priority(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
def create_task(
title: str,
priority: Priority,
tags: list[str],
due_date: Optional[str] = None
) -> dict:
return {
"title": title,
"priority": priority.value,
"tags": tags,
"due_date": due_date,
"completed": False
}
tasks: list[dict] = []
task1 = create_task("Learn TypeScript", Priority.HIGH, ["coding", "study"])
task2 = create_task("Buy groceries", Priority.LOW, ["personal"], "2024-12-31")
tasks.append(task1)
tasks.append(task2)
for task in tasks:
status = "done" if task["completed"] else "pending"
print(f"{task['title']} - {status}")
רמז: בטייפסקריפט תצטרכו להגדיר את צורת האובייקט של ה-task כ-type annotation.