לדלג לתוכן

5.1 הקדמה לטייפסקריפט הרצאה

מה זה טייפסקריפט - TypeScript

טייפסקריפט (TypeScript, בקיצור TS) היא שפת תכנות שנבנתה מעל ג׳אווהסקריפט. היא מוסיפה לג׳אווהסקריפט דבר אחד מרכזי - טיפוסים סטטיים (static types). במילים פשוטות: טייפסקריפט היא ג׳אווהסקריפט עם בדיקת טיפוסים.

  • את השפה פיתחה מייקרוסופט ב-2012, והיא קוד פתוח
  • טייפסקריפט היא superset של ג׳אווהסקריפט - כל קוד JS תקין הוא גם קוד TS תקין
  • הדפדפן לא מריץ TS ישירות - צריך לקמפל (להמיר) את הקוד ל-JS רגיל
  • היום היא סטנדרט בתעשייה - רוב הפרויקטים הגדולים (React, Angular, Vue, Next.js) משתמשים בה

למה צריך טיפוסים

בג׳אווהסקריפט אפשר לכתוב קוד כזה בלי שום אזהרה:

function add(a, b) {
    return a + b;
}

add(5, "3"); // "53" - string concatenation, not addition!
add(5);      // NaN - b is undefined

ב-JS אין שום בעיה עם הקוד הזה. הוא ירוץ בלי שגיאות - אבל יתנהג לא כמו שציפינו. בטייפסקריפט, השגיאות האלה נתפסות לפני שהקוד רץ:

function add(a: number, b: number): number {
    return a + b;
}

add(5, "3"); // ERROR: Argument of type 'string' is not assignable to parameter of type 'number'
add(5);      // ERROR: Expected 2 arguments, but got 1

למה טייפסקריפט - היתרונות

תפיסת באגים בזמן כתיבה - compile-time errors

הסוג הכי נפוץ של באגים ב-JS הוא באגים של טיפוסים - ניסיון לגשת ל-property שלא קיים, העברת ארגומנט מהסוג הלא נכון, שכחה לבדוק null. טייפסקריפט תופסת את כל אלה עוד לפני שהקוד רץ.

let user = { name: "Alice", age: 30 };

console.log(user.naem); // ERROR: Property 'naem' does not exist. Did you mean 'name'?

השלמה אוטומטית - autocomplete

כשה-IDE יודע מה הטיפוס של כל משתנה, הוא יכול להציע לכם את כל ה-properties והמתודות הזמינות. זה חוסך המון זמן ומונע שגיאות כתיב.

let name: string = "hello";
name. // the IDE shows: toUpperCase(), toLowerCase(), trim(), split(), includes() ...

תיעוד חי - self-documenting code

כשפונקציה מגדירה את הטיפוסים שלה, אתם יודעים בדיוק מה היא מצפה לקבל ומה היא מחזירה - בלי לקרוא תיעוד חיצוני:

function createUser(name: string, age: number, isAdmin: boolean): User {
    // just by reading the signature, you know exactly what this function needs
}

שיפוץ בטוח - refactoring

כשמשנים שם של property או מבנה של אובייקט, הקומפיילר מוצא מיד את כל המקומות שצריך לעדכן. ב-JS אתם צריכים לחפש ידנית ולקוות שלא פספסתם שום מקום.

טייפסקריפט היא superset של ג׳אווהסקריפט

הנקודה הזו חשובה מאוד: כל קוד JavaScript תקין הוא גם קוד TypeScript תקין. אפשר לקחת כל קובץ JS, לשנות את הסיומת ל-.ts, והוא יעבוד (אולי עם כמה אזהרות, אבל יעבוד).

// this is valid TypeScript AND valid JavaScript
let x = 5;
let name = "Alice";
console.log(name + " is " + x + " years old");

// this is valid TypeScript but NOT valid JavaScript (has type annotations)
let y: number = 10;
let greeting: string = "Hello";

זה אומר שלא צריך ללמוד שפה חדשה - צריך רק ללמוד את התוספות שטייפסקריפט מביאה.

השוואה לפייתון - Python typing

אם אתם מכירים את מערכת ה-type hints של פייתון, טייפסקריפט עובדת על אותו רעיון - אבל חזקה הרבה יותר:

# Python with type hints
def greet(name: str, age: int) -> str:
    return f"Hello {name}, you are {age} years old"

# Python does NOT enforce these types at runtime!
greet(123, "hello")  # runs without error, just gives wrong results
// TypeScript - same idea, but enforced
function greet(name: string, age: number): string {
    return `Hello ${name}, you are ${age} years old`;
}

greet(123, "hello"); // ERROR at compile time!

ההבדל המרכזי: בפייתון ה-type hints הם רק רמזים - פייתון לא אוכפת אותם (אלא אם משתמשים בכלי כמו mypy). בטייפסקריפט הטיפוסים נאכפים על ידי הקומפיילר.

התקנה - installation

טייפסקריפט מותקנת כחבילת npm:

# install TypeScript as a dev dependency
npm install -D typescript

הפלאג -D (קיצור של --save-dev) שומר את זה ב-devDependencies כי טייפסקריפט נחוצה רק בפיתוח - בפרודקשן רץ JS רגיל.

אחרי ההתקנה, יש לנו את הפקודה tsc (TypeScript Compiler):

# check version
npx tsc --version

הקומפיילר - tsc

הקומפיילר של טייפסקריפט ממיר קבצי .ts לקבצי .js:

# compile a single file
npx tsc hello.ts
# creates hello.js in the same directory

בואו ננסה. צרו קובץ hello.ts:

let message: string = "Hello from TypeScript!";
console.log(message);

function add(a: number, b: number): number {
    return a + b;
}

console.log(add(5, 3));

עכשיו קמפלו והריצו:

npx tsc hello.ts   # compile - creates hello.js
node hello.js       # run the JavaScript output

אם תסתכלו על hello.js שנוצר, תראו שכל הטיפוסים הוסרו:

let message = "Hello from TypeScript!";
console.log(message);

function add(a, b) {
    return a + b;
}

console.log(add(5, 3));

הטיפוסים קיימים רק בזמן פיתוח. ב-runtime רץ JS רגיל.

קובץ הגדרות - tsconfig.json

במקום להעביר אופציות בשורת הפקודה, יוצרים קובץ tsconfig.json בתיקיית הפרויקט:

# create a default tsconfig.json
npx tsc --init

זה יוצר קובץ עם המון אופציות (רובן מסומנות כהערות). בואו נכיר את החשובות:

{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "strict": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "lib": ["ES2020"],
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    },
    "include": ["src/**/*"],
    "exclude": ["node_modules"]
}

הסבר על האופציות העיקריות

  • target - לאיזו גרסת JS לקמפל. ES2020 היא בחירה טובה - מספיק מודרנית ונתמכת בכל הדפדפנים
  • module - מערכת המודולים. ESNext משתמשת ב-import/export המודרני
  • strict - מפעילה את כל בדיקות הטיפוסים המחמירות. תמיד תפעילו את זה
  • outDir - לאן לשים את קבצי ה-JS שנוצרים מהקומפילציה
  • rootDir - איפה נמצאים קבצי המקור (TS)
  • lib - אילו API מובנים זמינים (DOM, ES2020, וכו׳)
  • esModuleInterop - מאפשר import רגיל מחבילות CommonJS (תמיד כדאי להפעיל)
  • include - אילו קבצים לקמפל
  • exclude - אילו קבצים להתעלם מהם

כש-tsconfig.json קיים, מספיק להריץ npx tsc בלי שם קובץ - הוא יקמפל את הכל לפי ההגדרות.

דרכים להריץ טייפסקריפט

הדרך הקלאסית - tsc ואז node

npx tsc          # compile all TS files
node dist/app.js  # run the output

tsx - הרצה ישירה

tsx (לא לבלבל עם קבצי .tsx) הוא כלי שמריץ TS ישירות בלי צעד קומפילציה נפרד:

npm install -D tsx

# run TypeScript directly
npx tsx src/app.ts

# watch mode - re-runs on changes
npx tsx watch src/app.ts

זה שימושי מאוד לפיתוח כי חוסך את הצעד של קומפילציה ידנית.

Vite מטפלת בזה אוטומטית

בפרויקטי פרונטאנד עם Vite (שנלמד בהמשך עם React), טייפסקריפט עובדת אוטומטית - לא צריך לקמפל ידנית. Vite ממירה את הקוד תוך כדי פיתוח.

סוגי קבצים - ts. לעומת tsx.

  • ts. - קבצי טייפסקריפט רגילים
  • tsx. - קבצי טייפסקריפט שמכילים JSX (תחביר של React)
// file: utils.ts - regular TypeScript
function formatDate(date: Date): string {
    return date.toLocaleDateString();
}
// file: Button.tsx - TypeScript with JSX (React component)
function Button(props: { label: string }) {
    return <button>{props.label}</button>;
}

כרגע נעבוד רק עם קבצי .ts. כשנגיע ל-React נשתמש ב-.tsx.

מצב מחמיר - strict mode

ב-tsconfig.json ראינו את האופציה strict: true. היא מפעילה כמה בדיקות חשובות בבת אחת:

strictNullChecks

מונע גישה למשתנה שיכול להיות null או undefined בלי בדיקה:

// without strictNullChecks - no error, but crashes at runtime!
// with strictNullChecks:
function getLength(str: string | null): number {
    return str.length; // ERROR: 'str' is possibly 'null'
}

// the fix - check for null first
function getLength(str: string | null): number {
    if (str === null) {
        return 0;
    }
    return str.length; // OK - TS knows str is not null here
}

noImplicitAny

מחייב לציין טיפוס כשטייפסקריפט לא יכולה להסיק אותו:

// without noImplicitAny - parameter 'x' has type 'any' silently
// with noImplicitAny:
function double(x) {    // ERROR: Parameter 'x' implicitly has an 'any' type
    return x * 2;
}

// the fix - add type annotation
function double(x: number): number {
    return x * 2;
}

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

הבסיס - הוספת טיפוסים

הדבר הכי בסיסי בטייפסקריפט הוא הוספת טיפוס למשתנה:

// type annotation - we tell TS what type the variable is
let name: string = "Alice";
let age: number = 30;
let isStudent: boolean = true;

התחביר הוא: variableName: type. שימו לב לנקודתיים אחרי שם המשתנה.

הסקת טיפוסים - type inference

טייפסקריפט חכמה מספיק כדי להבין את הטיפוס לבד ברוב המקרים:

// TS infers the type automatically - no need to annotate!
let name = "Alice";     // TS knows this is string
let age = 30;            // TS knows this is number
let isStudent = true;    // TS knows this is boolean

name = 42; // ERROR: Type 'number' is not assignable to type 'string'

כש-TS יכולה להסיק את הטיפוס, אין צורך לכתוב אותו במפורש. הקוד נשאר נקי, והטיפוסים עדיין נאכפים.

מתי כן כדאי לכתוב טיפוס במפורש:
- פרמטרים של פונקציות - TS לא יכולה להסיק אותם
- כשמאתחלים משתנה בלי ערך
- כשרוצים טיפוס ספציפי יותר ממה ש-TS מסיקה

// TS can't infer parameter types - must annotate
function greet(name: string): string {
    return `Hello, ${name}!`;
}

// variable without initial value - must annotate
let score: number;
score = 100;

// want a more specific type than what TS would infer
let status: "active" | "inactive" = "active";

אימוץ הדרגתי - gradual adoption

אחד הדברים הכי טובים בטייפסקריפט הוא שאפשר להוסיף אותה לפרויקט JS קיים בהדרגה, קובץ אחרי קובץ:

  1. מתקינים טייפסקריפט ויוצרים tsconfig.json
  2. משנים את הסיומת של קובץ אחד מ-.js ל-.ts
  3. מתקנים את השגיאות שצצות
  4. עוברים לקובץ הבא

אפשר גם להוסיף allowJs: true ב-tsconfig כדי שקבצי JS ו-TS יעבדו יחד באותו פרויקט.

סיכום

  • טייפסקריפט היא ג׳אווהסקריפט עם טיפוסים סטטיים - superset של JS
  • היתרונות: תפיסת באגים מוקדם, השלמה אוטומטית, תיעוד, refactoring בטוח
  • הקומפיילר tsc ממיר TS ל-JS - הטיפוסים קיימים רק בזמן פיתוח
  • קובץ tsconfig.json מגדיר את אופציות הקומפילציה
  • אפשר להריץ עם tsc + node, עם tsx, או ש-Vite מטפלת בזה אוטומטית
  • תמיד הפעילו strict mode
  • טייפסקריפט תומכת בהסקת טיפוסים - לא חייבים לכתוב את הטיפוס בכל מקום
  • אפשר לאמץ בהדרגה בפרויקט קיים
  • דומה ל-type hints של פייתון, אבל נאכפת על ידי הקומפיילר