גנריקות בסוג-סקריפט

גנריקות בסוג-סקריפט

מאמר זה מסביר גנריקות בסוג-סקריפט.

YouTube Video

גנריקות בסוג-סקריפט

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

יסודות הגנריקות

גנריקות פועלות כמו תבניות שמקבלות טיפוסים כפרמטרים ומאפשרות לפונקציות ולמחלקות לטפל בטיפוסים שונים.

פונקציות גנריות

להלן דוגמה לפונקציה שבה סוגי הפרמטרים שלה מצוינים באמצעות גנריקות.

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity<number>(42));       // 42
6console.log(identity<string>("Hello"));  // Hello
  • T הוא טיפוס גנרי שמייצג את סוגי הפרמטרים של הפונקציה ואת ערך ההחזרה שלה. הטיפוס בפועל נקבע במועד קריאת הפונקציה.
  • על ידי פרמטריזציה מפורשת של <number> או <string>, הנך מציין את הטיפוס.

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

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity(42));       // 42
6console.log(identity("Hello"));  // Hello

מגבלות על גנריקות

על ידי הגדרת מגבלות על גנריקות, ניתן להגביל אותן לקבל רק טיפוסים מסוימים.

1function loggingIdentity<T extends { length: number }>(arg: T): T {
2    console.log(arg.length);
3    return arg;
4}
5
6loggingIdentity("Hello");  // 5
7loggingIdentity([1, 2, 3]);  // 3
8
9// loggingIdentity(42);  // Error: number does not have a length property.
  • הגדרת T extends { length: number } מציינת כי T חייב להיות טיפוס עם תכונת length. לכן, טיפוסים ללא תכונת length לא יתקבלו.

מחלקות גנריות

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

 1class Box<T> {
 2    private _value: T;
 3
 4    constructor(value: T) {
 5        this._value = value;
 6    }
 7
 8    public getValue(): T {
 9        return this._value;
10    }
11
12    public setValue(value: T): void {
13        this._value = value;
14    }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue());  // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue());  // Hello
  • Box<T> מציין כי הטיפוס T בשימוש בתוך המחלקה הוא גנרי. דבר זה מאפשר שימוש חוזר באותה מחלקה עבור טיפוסים שונים.

ממשקים גנריים

גם ממשקים יכולים להשתמש בגנריקות.

 1interface Pair<T, U> {
 2    first: T;
 3    second: U;
 4}
 5
 6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
 7console.log(numberStringPair);  // { first: 1, second: 'One' }
 8
 9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair);  // { first: true, second: [ 1, 2, 3 ] }
  • על ידי הגדרת שני טיפוסים גנריים עם Pair<T, U>, ניתן להגדיר אובייקט עם שילוב של סוגים שונים.

ארגומנטים מסוג ברירת מחדל

ניתן גם להגדיר סוג ברירת מחדל עבור ארגומנטים מסוג גנרי.

1function createArray<T = string>(length: number, value: T): T[] {
2    return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a"));   // ['a', 'a', 'a']
6console.log(createArray(3, 100));   // [100, 100, 100]
  • אנו מגדירים את ארגומנט סוג ברירת המחדל ל-string באמצעות <T = string>. אם לא מצויין סוג במפורש, T יהיה מסוג string.

כינויי סוג גנריים

ניתן להשתמש בגנריים גם ככינויי סוג (type).

 1type Result<T> = {
 2    success: boolean;
 3    data: T;
 4};
 5
 6const successResult: Result<number> = { success: true, data: 42 };
 7const errorResult: Result<string> = { success: false, data: "Error occurred" };
 8
 9console.log(successResult);  // { success: true, data: 42 }
10console.log(errorResult);    // { success: false, data: 'Error occurred' }
  • Result<T> מייצג אובייקט תוצאה המכיל נתונים מסוג T. בדרך זו, ניתן ליצור כינויי סוג גמישים באמצעות גנריים.

סוגים גנריים מרובים

על ידי שימוש בסוגים גנריים מרובים, ניתן להגדיר פונקציות ומחלקות גמישות יותר.

1function merge<T, U>(obj1: T, obj2: U): T & U {
2    return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged);  // { name: 'Alice', title: 'Engineer' }
  • הפונקציה merge מקבלת שני סוגים שונים T ו-U ומשלבת אותם כדי להחזיר אובייקט חדש.

סיכום

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

באמצעות שימוש בגנריים, ניתן לכתוב קוד עצמאי מסוגים לשימוש כללי, ולנצל את מערכת הסוגים החזקה של TypeScript.

תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.

YouTube Video