Cách sử dụng Decorator trong TypeScript

Decorator trong TypeScript là một tính năng mạnh mẽ cho phép các nhà phát triển thêm chức năng bổ sung vào các lớp, phương thức, thuộc tính và tham số. Chúng cung cấp một cách để sửa đổi hành vi của mã hiện có mà không thay đổi cấu trúc thực tế của nó. Hướng dẫn này sẽ giải thích cách sử dụng decorator trong TypeScript với các ví dụ dễ làm theo.

Decorator là gì?

Decorator là các hàm đặc biệt có thể áp dụng cho các lớp, phương thức, thuộc tính hoặc tham số. Chúng được gọi khi chạy và cho phép các nhà phát triển chú thích và sửa đổi mã theo cách khai báo. Để bật decorator trong dự án TypeScript, cờ experimentalDecorators phải được đặt thành true trong tệp tsconfig.json.

Kích hoạt Decorators trong TypeScript

Để sử dụng trình trang trí, trình biên dịch TypeScript phải được cấu hình để nhận dạng chúng. Điều này có thể thực hiện bằng cách đặt cờ experimentalDecorators thành true trong tệp tsconfig.json.

{
  "compilerOptions": {
    "target": "ES6",
    "experimentalDecorators": true
  }
}

Sau khi bật trình trang trí, bạn có thể sử dụng chúng trong suốt dự án.

Tạo một trình trang trí lớp

Một trình trang trí lớp được áp dụng cho một khai báo lớp và có thể được sử dụng để sửa đổi hoặc thay thế một định nghĩa lớp. Trình trang trí lớp được khai báo ngay phía trên lớp mà chúng trang trí, sử dụng ký hiệu @.

function LogClass(target: Function) {
  console.log(`Class ${target.name} is created.`);
}

@LogClass
class Person {
  constructor(public name: string) {}
}

const person = new Person('Alice');

Trong ví dụ này, trình trang trí LogClass ghi lại thông báo khi lớp Person được tạo. Trình trang trí được định nghĩa là một hàm chỉ lấy một đối số: hàm tạo của lớp đang được trang trí.

Phương pháp trang trí

Trình trang trí phương thức được áp dụng cho các phương thức trong một lớp. Chúng cho phép các nhà phát triển chặn các cuộc gọi phương thức, sửa đổi hành vi của chúng hoặc thực hiện các hoạt động bổ sung trước hoặc sau khi phương thức được thực thi.

function LogMethod(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Method ${propertyKey} is called with arguments: ${args}`);
    return originalMethod.apply(this, args);
  };

  return descriptor;
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);

Ở đây, trình trang trí LogMethod ghi lại tên phương thức và các đối số của nó bất cứ khi nào phương thức add được gọi. Nó bao bọc phương thức gốc trong một hàm mới thực hiện việc ghi nhật ký trước khi chuyển giao cho phương thức gốc.

Người trang trí bất động sản

Bộ trang trí thuộc tính được sử dụng để quan sát hoặc sửa đổi hành vi của các thuộc tính lớp. Không giống như bộ trang trí phương thức, chúng không có quyền truy cập vào chính giá trị thuộc tính, nhưng chúng có thể thêm siêu dữ liệu vào các thuộc tính.

function ReadOnly(target: Object, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false
  });
}

class Book {
  @ReadOnly
  title: string = 'TypeScript Guide';
}

const myBook = new Book();
myBook.title = 'New Title'; // This will cause an error in strict mode

Trong ví dụ này, trình trang trí ReadOnly được áp dụng cho thuộc tính title của lớp Book, biến nó thành chỉ đọc bằng cách đặt writable thành false.

Bộ trang trí tham số

Bộ trang trí tham số được sử dụng để chú thích hoặc sửa đổi các tham số phương thức. Chúng nhận được ba đối số: đối tượng mục tiêu, tên phương thức và chỉ mục tham số.

function LogParameter(target: Object, propertyKey: string, parameterIndex: number) {
  console.log(`Parameter in position ${parameterIndex} at ${propertyKey} method is decorated.`);
}

class UserService {
  greet(@LogParameter message: string): void {
    console.log(message);
  }
}

const userService = new UserService();
userService.greet('Hello, TypeScript!');

Trong ví dụ này, trình trang trí LogParameter được áp dụng cho tham số message của phương thức greet trong lớp UserService. Trình trang trí ghi lại thông tin về tham số được trang trí.

Phần kết luận

Decorator trong TypeScript cung cấp một cách mạnh mẽ để nâng cao chức năng mã mà không làm thay đổi cấu trúc của nó. Bằng cách tận dụng các decorator lớp, phương thức, thuộc tính và tham số, các nhà phát triển có thể dễ dàng thêm chức năng có thể tái sử dụng trên khắp các dự án của họ. Với các ví dụ được cung cấp trong hướng dẫn này, thật dễ dàng để bắt đầu sử dụng decorator trong TypeScript.