Hướng dẫn xử lý lỗi TypeScript cho người mới bắt đầu

Xử lý lỗi hiệu quả là rất quan trọng trong bất kỳ ngôn ngữ lập trình nào và TypeScript cũng không ngoại lệ. Xử lý lỗi đúng cách giúp tạo ra các ứng dụng mạnh mẽ và đáng tin cậy bằng cách quản lý các điều kiện bất ngờ một cách khéo léo. Hướng dẫn này sẽ đề cập đến những điều cơ bản về xử lý lỗi trong TypeScript và cung cấp các ví dụ thực tế cho người mới bắt đầu.

Hiểu về lỗi trong TypeScript

Lỗi trong TypeScript, giống như trong JavaScript, xảy ra trong thời gian chạy hoặc thời gian biên dịch. TypeScript cung cấp tính năng an toàn kiểu có thể phát hiện nhiều vấn đề tiềm ẩn tại thời gian biên dịch, nhưng lỗi thời gian chạy vẫn cần được quản lý đúng cách.

Xử lý lỗi cơ bản với trycatch

Trong TypeScript, bạn xử lý lỗi thời gian chạy bằng cách sử dụng các khối trycatch. Cách tiếp cận này cho phép bạn thực thi mã có thể gây ra lỗi và xử lý lỗi đó nếu xảy ra.

Ví dụ về trycatch

function divide(a: number, b: number): number {
  try {
    if (b === 0) {
      throw new Error("Cannot divide by zero");
    }
    return a / b;
  } catch (error) {
    console.error(error.message);
    return NaN; // Return NaN to indicate an error
  }
}

console.log(divide(10, 2)); // Output: 5
console.log(divide(10, 0)); // Output: Cannot divide by zero

Trong ví dụ này, hàm divide cố gắng chia hai số. Nếu số chia bằng 0, lỗi sẽ được ném ra và được khối catch bắt, khối này sẽ ghi lại thông báo lỗi.

Các loại lỗi tùy chỉnh

TypeScript cho phép bạn xác định các loại lỗi tùy chỉnh để thể hiện tốt hơn các điều kiện lỗi cụ thể. Các loại lỗi tùy chỉnh giúp phân loại lỗi và xử lý chúng hiệu quả hơn.

Tạo loại lỗi tùy chỉnh

class DivisionError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "DivisionError";
  }
}

function divide(a: number, b: number): number {
  try {
    if (b === 0) {
      throw new DivisionError("Cannot divide by zero");
    }
    return a / b;
  } catch (error) {
    if (error instanceof DivisionError) {
      console.error(`Custom Error: ${error.message}`);
    } else {
      console.error("An unexpected error occurred");
    }
    return NaN; // Return NaN to indicate an error
  }
}

console.log(divide(10, 2)); // Output: 5
console.log(divide(10, 0)); // Output: Custom Error: Cannot divide by zero

Ở đây, chúng tôi định nghĩa một lớp lỗi tùy chỉnh DivisionError mở rộng lớp Error tích hợp sẵn. Chúng tôi sử dụng lỗi tùy chỉnh này trong hàm divide để cung cấp cách xử lý lỗi cụ thể hơn.

Bảo vệ kiểu với instanceof

Các bảo vệ kiểu như instanceof giúp thu hẹp kiểu của đối tượng lỗi trong khối catch, cho phép bạn xử lý các kiểu lỗi khác nhau theo cách khác nhau.

Ví dụ về bảo vệ kiểu

function processInput(input: string | number) {
  try {
    if (typeof input === "string") {
      console.log(input.toUpperCase());
    } else {
      throw new Error("Input must be a string");
    }
  } catch (error) {
    if (error instanceof Error) {
      console.error(`Error: ${error.message}`);
    } else {
      console.error("An unknown error occurred");
    }
  }
}

processInput("hello"); // Output: HELLO
processInput(42); // Output: Error: Input must be a string

Ví dụ này trình bày cách bảo vệ kiểu trong khối catch để đảm bảo đối tượng lỗi là một thể hiện của Error, cho phép xử lý lỗi chính xác.

Sử dụng finally để dọn dẹp

Khối finally có thể được sử dụng để thực thi mã sẽ chạy bất kể có lỗi xảy ra hay không. Điều này hữu ích cho các hoạt động dọn dẹp như đóng tệp hoặc giải phóng tài nguyên.

Ví dụ với finally

function readFile(filePath: string): string {
  try {
    // Simulate reading a file
    if (filePath === "") {
      throw new Error("File path cannot be empty");
    }
    return "File content";
  } catch (error) {
    console.error(`Error: ${error.message}`);
    return "";
  } finally {
    console.log("Cleanup: Closing file");
  }
}

console.log(readFile("path/to/file")); // Output: File content
console.log(readFile("")); // Output: Error: File path cannot be empty
                            //         Cleanup: Closing file

Trong ví dụ này, khối finally đảm bảo rằng thông báo dọn dẹp được ghi lại bất kể có lỗi xảy ra hay không.

Phần kết luận

Xử lý lỗi hiệu quả là rất quan trọng để xây dựng các ứng dụng TypeScript đáng tin cậy. Bằng cách sử dụng trycatch, các kiểu lỗi tùy chỉnh, bảo vệ kiểu và finally, bạn có thể quản lý lỗi hiệu quả hơn và đảm bảo rằng ứng dụng của bạn hoạt động theo cách có thể dự đoán được ngay cả khi gặp phải các điều kiện bất ngờ.

Với các kỹ thuật này, bạn có thể xử lý lỗi một cách khéo léo và cải thiện tính mạnh mẽ của mã TypeScript. Thực hành các khái niệm này để trở nên thành thạo trong việc xử lý lỗi TypeScript và viết các ứng dụng có khả năng phục hồi tốt hơn.