לדלג לתוכן

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.