Trong JavaScript, TypeError là một đối tượng đại diện cho lỗi kết quả từ việc thực hiện một phép toán không thể thực hiện được, thường là vì một giá trị trong phép toán không phải là kiểu mong đợi.
Nhưng các kiểu (types) là gì? Theo phiên bản mới nhất của đặc tả JavaScript, ECMAScript, có chín kiểu dữ liệu và cấu trúc. Sáu trong số đó (thỉnh thoảng bảy nếu tính null), là kiểu dữ liệu nguyên thủy (primitive data types), bao gồm: string, number, bigint, boolean, undefined, và symbol. Trước khi hiểu tại sao TypeErrors xảy ra trong phép toán, hãy xem lại chín kiểu trong JavaScript. Nếu chúng ta bao giờ ở vị trí không chắc chắn về cách phân loại một kiểu, chúng ta có thể dùng toán tử typeof.
- undefined: Kiểu giá trị tự động được gán cho biến vừa được khai báo. Chúng ta thường gặp TypeError giá trị undefined khi quên định nghĩa hoặc thêm giá trị cho biến.
- Boolean: Kiểu dữ liệu logic chỉ chứa giá trị true hoặc false.
- Number: Kiểu dữ liệu số.
- String: Chuỗi ký tự bên trong backticks, dấu nháy đơn hoặc kép.
- BigInt: Kiểu dữ liệu số đôi khi gọi là bignums trong ngôn ngữ khác.
- Symbol: Giá trị đại diện cho định danh duy nhất được tạo bằng cách gọi hàm Symbol.
- Object: Kiểu cấu trúc và gần như bất cứ thứ gì từ khóa 'new' có thể tạo, như array, object, map, set, v.v.
- Function: Kiểu cấu trúc không phải dữ liệu khác là đoạn mã có thể được gọi bởi các đoạn mã khác.
- null: Thường là giá trị cố ý đại diện cho đối tượng hoặc địa chỉ không tồn tại.
Các TypeError phổ biến nhất trong JavaScript và cách sửa
TypeErrors có thể bị ném khi cố thay đổi giá trị không thể thay đổi hoặc khi sử dụng giá trị theo cách không phù hợp. Nó cũng có thể xảy ra khi một đối số được truyền cho hàm không tương thích với kiểu mong đợi bởi hàm hoặc toán tử bên trong hàm.
Thay đổi giá trị không thể thay đổi
Khi bạn dùng từ khóa const gán giá trị cho cái gì đó, nghĩa là nó là hằng số (constant), nó sẽ không thay đổi. Cố thay đổi giá trị của biến hằng sẽ dẫn đến TypeError.
const a = 5 a = "5" // Uncaught TypeError: Assignment to constant variable.
Chúng ta có thể sửa bằng cách đơn giản đổi tên định danh (identifier) chúng ta muốn dùng cho chuỗi "5".
const a = 5 const b = "5"
Sử dụng giá trị theo cách không phù hợp
Các nhà phát triển cũng phải đảm bảo giá trị được dùng như ý định. Trong ví dụ dưới, "Cat" và "garfield" bị đảo ngược khi cố xác minh garfield có phải instance của hàm Cat() hay không.
function Cat() {}
function Dog() {}
let garfield = new Cat()
Cat instanceof garfield // Uncaught TypeError: Right-hand side of 'instanceof' is not callable
Chúng ta sửa bằng cách sửa thứ tự hai cái.
function Cat() {}
function Dog() {}
let garfield = new Cat()
garfield instanceof Cat
Đối số không tương thích với kiểu mong đợi của hàm
Khi viết mã cho một phép toán, nhà phát triển phải chắc chắn dùng giá trị theo cách có thể đạt kết quả mong muốn. Giá trị null có thể dùng cố ý để chỉ sự vắng mặt của đối tượng, nhưng cách dùng dưới đây sẽ dẫn đến TypeError vì nó được dùng như đối số không tương thích với kiểu mong đợi của hàm.
function readingErrorsAreImportant(a){
if(a.length === 5){
return "equals five"
} else if(a.length > 5) {
return "Greater than five"
} else {
return "Less than five"
}
}
console.log(readingErrorsAreImportant(null))
// Uncaught TypeError: Cannot read property 'length' of null
Chúng ta sửa bằng cách truyền vào kiểu giá trị nó mong đợi. Như kiểu số (numeric value type).
function readingErrorsAreImportant(a){
if(a.length === 5){
return "equals five"
} else if(a.length > 5) {
return "Greater than five"
} else {
return "Less than five"
}
}
console.log(readingErrorsAreImportant(10))
Kết luận
Việc hiểu tại sao mã của bạn ném type error rất quan trọng để bạn hiểu cách debug (gỡ lỗi) nó. Nếu bạn bao giờ ở vị trí không chắc chắn về cách phân loại kiểu, toán tử typeof sẽ trả về cho bạn một trong chín kiểu dữ liệu hoặc cấu trúc, để hiểu tốt hơn về cách bạn nên tiến hành debug.