TypeScript - Never: Hiểu về Kiểu Bottom
Xin chào, những người học lập trình!I Hôm nay, chúng ta sẽ cùng tìm hiểu một trong những kiểu bí ẩn của TypeScript: kiểu never
. Đừng lo lắng nếu bạn mới bắt đầu học lập trình - Tôi sẽ hướng dẫn bạn từng bước, giống như tôi đã làm cho hàng trăm học sinh trong những năm dạy học của mình. Vậy, hãy lấy饮料 yêu thích của bạn, và cùng bắt đầu hành trình thú vị vào thế giới của TypeScript!
Kiểu never
là gì?
Kiểu never
trong TypeScript thường được gọi là "kiểu bottom" hoặc "kiểu rỗng". Nó đại diện cho một kiểu mà không bao giờ xảy ra. Bây giờ, bạn có thể đang nghĩ, "Tại sao chúng ta lại cần một kiểu không bao giờ xảy ra?" Well, những người bạn tò mò, nó hữu ích hơn bạn tưởng!
Khi nào sử dụng never
?
- Để đại diện cho các tình huống không thể xảy ra
- Để xử lý các kiểm tra toàn diện
- Trong các hàm không bao giờ trả về
Hãy cùng xem một số ví dụ để làm rõ hơn các khái niệm này.
Ví dụ 1: Đại diện cho các tình huống không thể xảy ra
function throwError(message: string): never {
throw new Error(message);
}
let result = throwError("Oops! Something went wrong!");
console.log(result); // Dòng này sẽ không bao giờ được Reached
Trong ví dụ này, hàm throwError
đảm bảo rằng sẽ ném ra một lỗi và không bao giờ trả về bình thường. Do đó, kiểu trả về của nó là never
.
Hãy nghĩ như này: Nếu bạn đang nướng bánh và công thức nói "nướng đến khi nào không còn", bạn biết rằng bánh không ra khỏi lò!
Ví dụ 2: Kiểm tra toàn diện
type Shape = "circle" | "square" | "triangle";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return Math.PI * Math.pow(5, 2);
case "square":
return 10 * 10;
case "triangle":
return (10 * 5) / 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
Ở đây, never
giúp chúng ta đảm bảo rằng chúng ta đã bao gồm tất cả các hình dạng có thể. Nếu chúng ta thêm một hình dạng mới vào kiểu Shape
nhưng quên thêm một trường hợp cho nó trong getArea
, TypeScript sẽ cho chúng ta một lỗi. Nó giống như có một trợ lý hữu ích nhắc nhở bạn khi bạn quên điều gì!
Ví dụ 3: Các hàm không bao giờ trả về
function infiniteLoop(): never {
while (true) {
console.log("This loop never ends!");
}
}
Hàm này sẽ chạy mãi mãi (hoặc cho đến khi máy tính của bạn hết bộ nhớ). Vì nó không bao giờ kết thúc thực thi, kiểu trả về của nó là never
. Nó giống như nói với bạn bè rằng bạn sẽ ngừng nói "never" - họ biết rằng họ sẽ có một cuộc trò chuyện dài!
Kiểu never
vs. void
Bây giờ, bạn có thể đang tự hỏi, "Kiểu never
khác gì với void
?" Câu hỏi tuyệt vời! Hãy cùng phân tích.
void
Kiểu void
được sử dụng khi một hàm không trả về bất kỳ giá trị nào, nhưng nó vẫn hoàn thành việc thực thi.
function logMessage(message: string): void {
console.log(message);
}
logMessage("Hello, TypeScript!"); // Hàm này trả về `undefined`
never
Kiểu never
, mặt khác, được sử dụng khi một hàm không bao giờ hoàn thành việc thực thi hoặc luôn ném ra một lỗi.
function failwithError(message: string): never {
throw new Error(message);
}
failwithError("This function never returns!");
Hãy nghĩ như này: void
giống như đi đến một cửa hàng và trở về tay không, trong khi never
giống như bắt đầu một hành trình không có điểm đến - bạn không bao giờ trở về!
Các ứng dụng thực tế của never
Hãy cùng xem một số ví dụ thực tế hơn nơi never
có thể hữu ích.
Ví dụ 4: Bảo vệ kiểu
type Square = { kind: "square", size: number };
type Circle = { kind: "circle", radius: number };
type Shape = Square | Circle;
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function getArea(shape: Shape) {
switch (shape.kind) {
case "square": return shape.size * shape.size;
case "circle": return Math.PI * shape.radius ** 2;
default: return assertNever(shape); // Lỗi nếu shape không phải Square hoặc Circle
}
}
Trong ví dụ này, assertNever
giúp chúng ta bắt được bất kỳ trường hợp nào chúng ta có thể bỏ sót. Nó giống như có một mạng an toàn khi bạn đang học cách ném 类型!
Ví dụ 5: Phát hiện mã không thểReached
function neverReaches(): never {
while (true) {
// Một số thao tác
}
console.log("This line will never be reached"); // Lỗi TypeScript
}
TypeScript thông minh đủ để biết rằng câu lệnh console.log
sẽ không bao giờ đượcReached, và nó sẽ cho bạn một lỗi. Nó giống như có một GPS告诉 bạn khi bạn đang cố gắng lái xe đến một nơi không tồn tại!
Phương thức và thuộc tính của never
Bây giờ, bạn có thể đang tự hỏi nếu never
có bất kỳ phương thức hoặc thuộc tính nào. Sự thật là, never
không có bất kỳ phương thức hoặc thuộc tính nào của riêng nó vì nó đại diện cho một kiểu mà không bao giờ xảy ra. Tuy nhiên, nó vẫn là một phần quan trọng của hệ thống kiểu TypeScript.
Dưới đây là bảng tóm tắt những gì bạn có thể (hoặc không thể) làm với never
:
Thao tác | Kết quả | Giải thích |
---|---|---|
Gán cho never
|
✅ Cho phép | Bất kỳ kiểu nào cũng có thể được gán cho never
|
Gán never cho các kiểu khác |
❌ Không cho phép |
never không thể được gán cho bất kỳ kiểu nào khác |
Gọi phương thức trên never
|
❌ Không cho phép | Vì never không bao giờ xảy ra, bạn không thể gọi phương thức trên nó |
Sử dụng never trong các union |
✅ Cho phép nhưng không có tác dụng |
never bị bỏ qua trong các kiểu union |
Sử dụng never trong các intersection |
✅ Cho phép và kết quả là never
|
Bất kỳ kiểu nào giao với never sẽ kết quả là never
|
Kết luận
Và đây là nó, các học trò yêu quý của tôi! Chúng ta đã cùng nhau hành trình qua vùng đất của never
, khám phá từng ngóc ngách. Nhớ rằng, never
giống như người bạn luôn hủy bỏ kế hoạch - họ không bao giờ xuất hiện, nhưng họ vẫn quan trọng để nhớ đến!
Hiểu never
có thể seem khó khăn ban đầu, nhưng với sự luyện tập, bạn sẽ thấy nó là một công cụ vô giá trong bộ công cụ TypeScript của bạn. Nó giúp mã của bạn trở nên vững chắc hơn, bắt được các lỗi tiềm ẩn và thậm chí làm bạn suy nghĩ sâu hơn về hành vi của hàm của bạn.
Tiếp tục lập trình, tiếp tục học hỏi, và đừng bao giờ nói "never" để thử những điều mới trong TypeScript! Đến gặp lại lần sau, chúc các bạn ít lỗi biên dịch và suy luận kiểu mạnh mẽ!
Credits: Image by storyset