Bảo vệ kiểu TypeScript

Type guards là một tính năng mạnh mẽ trong TypeScript cho phép các nhà phát triển thực hiện kiểm tra thời gian chạy để thu hẹp loại của một biến. Điều này đảm bảo thông tin loại chính xác hơn, dẫn đến mã an toàn hơn và dễ dự đoán hơn. Bài viết này khám phá type guards là gì và cách sử dụng chúng hiệu quả.

Type Guards là gì?

Type guards là các biểu thức thực hiện kiểm tra thời gian chạy và cho phép TypeScript suy ra một kiểu cụ thể hơn cho một biến. Chúng giúp phân biệt giữa các kiểu khác nhau, đặc biệt là khi xử lý các kiểu hợp nhất. Type guards có thể được triển khai bằng nhiều kỹ thuật khác nhau, bao gồm:

  • Các thuật ngữ kiểu do người dùng định nghĩa
  • Khẳng định loại
  • Kiểm tra trường hợp
  • Sử dụng toán tử typeof
  • Sử dụng toán tử in

Các thuật ngữ kiểu do người dùng định nghĩa

Các vị từ kiểu do người dùng định nghĩa là các hàm trả về giá trị boolean và có kiểu trả về đặc biệt cho biết kiểu của biến đang được kiểm tra. Sau đây là cách tạo và sử dụng chúng:

function isString(value: any): value is string {
  return typeof value === 'string';
}

function printString(value: any) {
  if (isString(value)) {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log('Not a string');
  }
}

Trong ví dụ trên, isString là một thuật ngữ kiểu do người dùng định nghĩa giúp TypeScript hiểu rằng value là một chuỗi trong khối if.

Khẳng định loại

Khẳng định kiểu cho TypeScript biết cách xử lý một biến như một kiểu nhất định. Phương pháp này không thực hiện kiểm tra thời gian chạy nhưng thông báo cho trình biên dịch TypeScript về kiểu. Ví dụ:

function printLength(value: any) {
  console.log((value as string).length); // Assert value is a string
}

Trong ví dụ này, value as string yêu cầu TypeScript cho rằng value là một chuỗi mà không cần kiểm tra thời gian chạy.

Kiểm tra trường hợp

Kiểm tra thể hiện được sử dụng để xác định xem một đối tượng có phải là thể hiện của một lớp cụ thể hay không. Điều này hữu ích để thu hẹp các loại khi làm việc với các lớp:

class Dog {
  bark() { console.log('Woof'); }
}

class Cat {
  meow() { console.log('Meow'); }
}

function speak(animal: Dog | Cat) {
  if (animal instanceof Dog) {
    animal.bark(); // TypeScript knows animal is a Dog here
  } else {
    animal.meow(); // TypeScript knows animal is a Cat here
  }
}

Trong ví dụ này, toán tử instanceof giúp TypeScript suy ra loại của animal dựa trên lớp của nó.

Sử dụng toán tử typeof

Toán tử typeof có thể được sử dụng để kiểm tra các kiểu nguyên thủy như string, numberboolean:

function processValue(value: string | number) {
  if (typeof value === 'string') {
    console.log(value.toUpperCase()); // TypeScript knows value is a string here
  } else {
    console.log(value.toFixed(2)); // TypeScript knows value is a number here
  }
}

Tại đây, typeof được sử dụng để kiểm tra xem valuestring hay number và thu hẹp kiểu dữ liệu cho phù hợp.

Sử dụng toán tử in

Toán tử in kiểm tra sự hiện diện của một thuộc tính trong một đối tượng. Điều này hữu ích để phân biệt giữa các loại có chung các thuộc tính:

interface Bird {
  fly: () => void;
}

interface Fish {
  swim: () => void;
}

function move(creature: Bird | Fish) {
  if ('fly' in creature) {
    creature.fly(); // TypeScript knows creature is a Bird here
  } else {
    creature.swim(); // TypeScript knows creature is a Fish here
  }
}

Trong ví dụ này, toán tử in giúp TypeScript xác định xem creatureBird hay Fish dựa trên sự hiện diện của phương thức.

Phần kết luận

TypeScript type guards là công cụ thiết yếu để làm việc với các kiểu theo cách linh hoạt và an toàn. Chúng cho phép kiểm tra kiểu chính xác hơn và có thể ngăn ngừa lỗi thời gian chạy bằng cách đảm bảo sử dụng đúng kiểu trong các tình huống khác nhau. Hiểu và sử dụng type guards hiệu quả có thể dẫn đến mã TypeScript mạnh mẽ và dễ bảo trì hơn.