Sự Khác Biệt Giữa TypeScript unknown và any
Trong TypeScript, cả unknown và any đều đại diện cho các giá trị có kiểu không rõ ràng tại thời điểm biên dịch. Ban đầu, chúng có thể trông giống nhau, nhưng hành vi và tác động của chúng đến an toàn kiểu rất khác nhau.
Việc chọn đúng kiểu có thể tạo ra sự khác biệt giữa mã an toàn, dễ bảo trì và một mã nguồn đầy rẫy sự cố thời gian chạy.
Bài viết này sẽ phân tích sự khác biệt, kèm theo các ví dụ, thực hành tốt nhất và bảng tóm tắt để tham khảo nhanh.
Các Sự Khác Biệt Chính Giữa unknown và any
1. An Toàn Kiểu
any: Hoàn toàn vô hiệu hóa việc kiểm tra kiểu. Bạn có thể thực hiện bất kỳ thao tác nào trên nó, ngay cả những thao tác không hợp lệ, và trình biên dịch sẽ không báo lỗi.unknown: Là sự thay thế an toàn về kiểu. Bạn phải thu hẹp hoặc khẳng định kiểu trước khi sử dụng nó.
typescript
let valueAny: any;
let valueUnknown: unknown;
valueAny = "Xin chào";
console.log(valueAny.toUpperCase()); // ✅ Biên dịch thành công, có thể lỗi thời gian chạy
valueUnknown = "Xin chào";
console.log(valueUnknown.toUpperCase()); // ❌ Lỗi: phải thu hẹp trước
2. Hạn Chế Sử Dụng
any: Có thể gán cho bất kỳ kiểu nào và cho phép bất kỳ thao tác nào.unknown: Cần kiểm tra loại hoặc khẳng định rõ ràng.
typescript
let valueAny: any = "Xin chào";
let str: string = valueAny; // ✅ Hoạt động, nhưng không an toàn
valueAny.nonExistentMethod(); // ✅ Biên dịch, 💥 lỗi thời gian chạy
let valueUnknown: unknown = "Xin chào";
// ❌ let str2: string = valueUnknown;
if (typeof valueUnknown === "string") {
console.log(valueUnknown.toUpperCase()); // ✅ An toàn
}
3. Quy Tắc Gán
any: Hai chiều - có thể gán từ và đến bất cứ thứ gì.unknown: Bất cứ thứ gì có thể được gán chounknown, nhưngunknownchỉ có thể được gán choanyhoặcunknown(trừ khi đã thu hẹp).
typescript
let valueAny: any;
let valueUnknown: unknown;
valueAny = 42;
let num1: number = valueAny; // ✅ Hoạt động
valueUnknown = 42;
// ❌ let num2: number = valueUnknown;
let anyVar: any = valueUnknown; // ✅ Cho phép
let unknownVar: unknown = valueAny; // ✅ Cho phép
4. Triết Lý Sử Dụng
-
any:- Bỏ qua hệ thống kiểu.
- Thường dùng trong di chuyển từ JavaScript sang TypeScript.
- Hữu ích cho việc tạo mẫu nhanh hoặc làm việc với thư viện không có định nghĩa kiểu.
-
unknown:- Buộc phải kiểm tra rõ ràng.
- Thích hợp để xử lý phản hồi API, đầu vào của người dùng, hoặc dữ liệu bên ngoài.
- An toàn hơn trong các mã nguồn TypeScript hiện đại.
typescript
// Phản hồi API - không an toàn
function fetchData(): any {
return { name: "Alice", age: 25 };
}
let dataAny = fetchData();
console.log(dataAny.name.toUpperCase()); // ❌ Nguy hiểm nếu 'name' không phải là chuỗi
// Phản hồi API - an toàn
function fetchDataSafe(): unknown {
return { name: "Alice", age: 25 };
}
let dataUnknown = fetchDataSafe();
if (typeof dataUnknown === "object" && dataUnknown !== null && "name" in dataUnknown) {
console.log((dataUnknown as { name: string }).name.toUpperCase()); // ✅ An toàn
}
5. Dễ Sai Lầm So Với An Toàn
any: Dễ gây ra sự cố thời gian chạy.unknown: Trình biên dịch đảm bảo an toàn.
typescript
let valueAny: any = 42;
valueAny.toUpperCase(); // ❌ Biên dịch, 💥 lỗi thời gian chạy
let valueUnknown: unknown = 42;
// ❌ valueUnknown.toUpperCase(); (lỗi thời gian biên dịch, an toàn)
Thực Hành Tốt Nhất
- 🚫 Tránh sử dụng
anykhi có thể – nó làm yếu đi lợi ích cốt lõi của TypeScript. - ✅ Sử dụng
unknowncho dữ liệu động (API, JSON, đầu vào của người dùng). - 🔍 Thu hẹp
unknownvới các bảo vệ kiểu trước khi sử dụng.
typescript
function isString(value: unknown): value is string {
return typeof value === "string";
}
let input: unknown = "Xin chào";
if (isString(input)) {
console.log(input.toUpperCase()); // ✅ An toàn
}
Bảng Tóm Tắt
| Tính Năng | any |
unknown |
|---|---|---|
| An Toàn Kiểu | ❌ Không có, vô hiệu hóa kiểm tra kiểu | ✅ Bắt buộc kiểm tra trước khi sử dụng |
| Các Thao Tác Cho Phép | Bất kỳ thao tác nào | Chỉ sau khi đã thu hẹp |
| Gán | Có thể gán cho/từ bất kỳ thứ gì | Chỉ có thể gán cho any/unknown |
| Trường Hợp Sử Dụng | Mã cũ, di chuyển, hack nhanh | Xử lý an toàn dữ liệu bên ngoài |
| Rủi Ro Thời Gian Chạy | Cao | Thấp (với kiểm tra) |
Kết Luận
any: Là một con dao hai lưỡi. Tiện lợi, nhưng nguy hiểm nếu lạm dụng. Tốt nhất nên giữ cho di chuyển mã cũ hoặc sửa chữa nhanh.unknown: Là sự thay thế an toàn và hiện đại. Nó cho phép bạn xử lý các giá trị động mà không hy sinh an toàn kiểu.
👉 Nguyên Tắc Chung:
- Hãy sử dụng
unknowntrong các dự án TypeScript hiện đại. - Chỉ sử dụng
anykhi bạn thực sự cần phải bỏ qua hệ thống kiểu.
Bằng cách ưu tiên unknown hơn any, bạn sẽ viết mã TypeScript an toàn hơn, dễ dự đoán hơn, và dễ bảo trì hơn.