דקורטורים ב-TypeScript

דקורטורים ב-TypeScript

מאמר זה מסביר את הדקורטורים ב-TypeScript.

YouTube Video

דקורטורים ב-TypeScript

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

יסודות הדקורטורים

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

1{
2  "compilerOptions": {
3    "experimentalDecorators": true
4  }
5}
  • כדי להשתמש בדקורטורים, עליך לאפשר את האפשרות experimentalDecorators בקובץ tsconfig.json.

סוגי דקורטורים

ב-TypeScript ניתן להשתמש בחמשת הסוגים הבאים של דקורטורים.

  • דקורטור של מחלקה דקורטור שמיושם למחלקה.
  • דקורטור של מתודה דקורטור שמיושם למתודה של מחלקה.
  • דקורטור של מאפיין גישה דקורטור שמיושם ל-getter או setter של מאפיין של מחלקה.
  • דקורטור של מאפיין דקורטור שמיושם למאפיין של מחלקה.
  • דקורטור של פרמטר דקורטור שמיושם לפרמטר של מתודה.

דקורטור של מחלקה

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

 1function Logger(constructor: Function) {
 2    console.log(`Class ${constructor.name} is being constructed`);
 3}
 4
 5@Logger
 6class Person {
 7    constructor(public name: string) {}
 8}
 9
10const person = new Person('John');
11// Output: Class Person is being constructed

בדוגמה זו, הדקורטור Logger מוחל על המחלקה, והודעה מוצגת בקונסול כאשר המחלקה מאותחלת.

דקורטור של שיטה

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

  1. הפרוטוטייפ של המחלקה
  2. שם השיטה
  3. מתאר התכונה של השיטה
 1function LogExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalMethod = descriptor.value;
 3
 4    descriptor.value = function (...args: any[]) {
 5        console.time(propertyKey);
 6        const result = originalMethod.apply(this, args);
 7        console.timeEnd(propertyKey);
 8        return result;
 9    };
10}
11
12class MathOperations {
13  @LogExecutionTime
14  add(a: number, b: number): number {
15    return a + b;
16  }
17}
18
19const math = new MathOperations();
20math.add(2, 3);
21// Output: add: 0.000ms (execution time is displayed)

בדוגמה זו, דקורטור LogExecutionTime מיושם על השיטה, וזמן הביצוע של השיטה נרשם.

דקורטור גישה

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

 1function LogAccess(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
 2    const originalGet = descriptor.get;
 3    const originalSet = descriptor.set;
 4
 5    if (originalGet) {
 6        descriptor.get = function () {
 7            console.log(`Getter called for ${propertyKey}`);
 8            return originalGet.call(this);
 9        };
10    }
11
12    if (originalSet) {
13        descriptor.set = function (value: any) {
14            console.log(`Setter called for ${propertyKey} with value: ${value}`);
15            originalSet.call(this, value);
16        };
17    }
18}
19
20class Car {
21    private _speed: number = 0;
22
23    @LogAccess
24    get speed() {
25        return this._speed;
26    }
27
28    set speed(value: number) {
29        this._speed = value;
30    }
31}
32
33const car = new Car();
34car.speed = 120;               // Setter called for speed with value: 120
35console.log(car.speed);       // Getter called for speed → 120

בדוגמה זו, נעשה שימוש במקשט גישה כדי לתעד פלט כאשר ה־getter וה־setter נקראים.

דקורטור תכונה

דקורטורי תכונה מיושמים על תכונות מחלקה, אך לא יכולים לשנות ישירות את ערך התכונה או את התנהגותה. הם משמשים לקבלת מטא-נתונים של תכונות.

 1function Readonly(target: any, propertyKey: string) {
 2    Object.defineProperty(target, propertyKey, {
 3        writable: false
 4    });
 5}
 6
 7class Book {
 8    @Readonly
 9    title: string = "TypeScript Guide";
10}
11
12const book = new Book();
13book.title = "New Title"; // Error: Cannot assign to read only property 'title'

בדוגמה זו, דקורטור Readonly מיושם על התכונה title, והתכונה הופכת לקריאה בלבד.

דקורטור פרמטר

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

  1. הפרוטוטייפ של המחלקה
  2. שם השיטה
  3. אינדקס פרמטר
 1function LogParameter(target: any, propertyKey: string, parameterIndex: number) {
 2    console.log(`Parameter at index ${parameterIndex} in method ${propertyKey} was decorated.`);
 3}
 4
 5class User {
 6    greet(@LogParameter message: string) {
 7        console.log(message);
 8    }
 9}
10
11const user = new User();
12user.greet('Hello!');
13// Output: Parameter at index 0 in method greet was decorated.

בדוגמה זו, דקורטור LogParameter מיושם על הפרמטר הראשון של שיטת greet, וכאשר השיטה מופעלת, הוא רושם שהפרמטר מעוטר.

דוגמאות מעשיות לדקורטורים

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

1@Component({
2    selector: 'app-root',
3    template: '<h1>Hello World</h1>',
4})
5export class AppComponent {}

לפיכך, דקורטורים משמשים לעיתים קרובות כחלק מרכזי בפריימוורקים וספריות, ועוזרים לשמור על קוד תמציתי וברור.

סיכום דקורטורים

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

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

YouTube Video