TypeScript: So sánh unknown và any, null và undefined

⏱︎

Read time:

3–4 minutes
TypeScript unknown, any, null và undefined

Bốn từ khóa này đều xuất hiện nhiều khi làm việc với TypeScript, cùng bắt tay vào phân biệt nhé ✌️

Kiểu dữ liệu: unknown và any

Cả any và unknown đều cho phép bạn gán bất kỳ kiểu dữ liệu nào (chuỗi, số, object, hàm…) cho biến đó. Tuy nhiên, triết lý an toàn của chúng hoàn toàn trái ngược nhau:

  • any (Buông xuôi): Khi bạn dùng any, TypeScript sẽ tắt toàn bộ cơ chế kiểm tra lỗi. Nó cho phép bạn làm bất cứ điều gì với biến đó (gọi hàm, chấm thuộc tính) mà không hề gạch đỏ. Đây là nguyên nhân lớn nhất gây lỗi sập nguồn đột ngột (Crash) lúc runtime.
  • unknown (Cẩn trọng): Đúng như cái tên “Chưa rõ kiểu”, unknown cho phép bạn bỏ gì vào cũng được, nhưng cấm tuyệt đối không cho bạn đem ra sử dụng trừ khi bạn chứng minh được kiểu dữ liệu của nó thông qua việc kiểm tra (typeof, instanceof).
// Hàm toFixed() để convert 1 số sang 1 string, method này chỉ available cho biến kiểu số

// --- TRƯỜNG HỢP DÙNG ANY ---
let bienAny: any = "Xin chào Linh";
bienAny.toFixed(2); 
//  TS KHÔNG báo lỗi khi gõ code. 
// ❌ Nhưng khi CHẠY chương trình sẽ bị CRASH lập tức vì Chuỗi không có hàm toFixed!

// --- TRƯỜNG HỢP DÙNG UNKNOWN ---
let bienUnknown: unknown = "Xin chào Linh";
// bienUnknown.toFixed(2); //  TS GẠCH ĐỎ NGAY: Object is of type 'unknown'.

// CÁCH DÙNG ĐÚNG VỚI UNKNOWN (Phải dùng Type Guard để kiểm tra):
if (typeof bienUnknown === "number") {    
    bienUnknown.toFixed(2); //  Lúc này TS sẽ cho phép chạy vào đây
}
Tiêu chíanyunknown
Nhận mọi giá trịCóCó
Dùng ngay mà chưa kiểm traCóKhông
Khả năng che giấu lỗiCaoThấp hơn
Nên dùng cho dữ liệu chưa tin cậyKhông nênNên dùng rồi thu hẹp kiểu

Giá trị của biến: null và undefined

Cả hai đều đại diện cho việc “không có dữ liệu”, nhưng ngữ cảnh sinh ra của chúng khác nhau:

  • undefined (Chưa có giá trị): Là trạng thái biến đã được khai báo nhưng chưa được gán giá trị, hoặc một thuộc tính không tồn tại trong object. Trạng thái này thường do hệ thống tự động gán.
  • null (Giá trị trống rỗng cố ý): Là một giá trị mà lập trình viên chủ động gán để biểu thị rằng biến này hiện tại đang trống rỗng, không chứa đối tượng nào cả.
Giá trịÝ nghĩa thường dùngVí dụ
undefinedChưa được gán hoặc thuộc tính không tồn tạiNgười dùng không gửi trường phone
nullChủ động biểu diễn “không có giá trị”API trả avatar: null
// 1. Hệ thống tự gán undefined
let userName: string;
console.log(userName); // Kết quả: undefined (Vì đã gán gì đâu)

const hocSinh = { ten: "An" };
console.log(hocSinh.tuoi); // Kết quả: undefined (Vì thuộc tính 'tuoi' không tồn tại)

// 2. Lập trình viên chủ động gán null
let currentUser: string | null = "Linh";
// Khi user đăng xuất, ta chủ động xóa dữ liệu bằng null
currentUser = null; 

// 3. So sánh bằng dấu == và ===
console.log(null == undefined);  // true  (So sánh lỏng lẻo: đều là "không có gì")
console.log(null === undefined); // false (So sánh nghiêm ngặt: khác nhau hoàn toàn)

Kinh nghiệm xương máu khi viết Playwright / TypeScript

  1. Hãy né xa any: Khi viết hàm nhận dữ liệu động (như đọc file JSON hoặc response từ API), hãy dùng unknown. Sau đó dùng if (typeof ...) để ép kiểu, code của bạn sẽ không bao giờ bị lỗi ngầm bất ngờ.
  2. Bật strictNullChecks: true: Trong file cấu hình tsconfig.json, hãy chắc chắn đã bật cờ này. TypeScript sẽ bắt bạn phải kiểm tra xem một phần tử (Locator) có bị null hoặc undefined hay không trước khi bạn thực hiện các lệnh .click() hoặc .fill() trong Playwright, giúp bài test của bạn chạy cực kỳ ổn định trên CI/CD.