Cách sửa lỗi TypeScript: Variable 'variableName' is used before being assigned

beginner🔵 TypeScript2026-03-31| TypeScript 2.7+ khi bật strictNullChecks hoặc chế độ strict mode.

Error Message

Variable 'variableName' is used before being assigned.
#typescript#phat-trien-web#meo-lap-trinh

Tại sao lỗi này xảy ra

TypeScript về cơ bản là tấm lưới an toàn của bạn. Lỗi cụ thể này xuất hiện khi trình biên dịch không chắc chắn 100% rằng một biến sẽ có giá trị tại thời điểm bạn cố gắng sử dụng nó. Đây là một tính năng cốt lõi của strictNullChecks, được thiết kế để ngăn chặn các lỗi undefined trước khi chúng tiếp cận người dùng.

let discount: number;
const isFlashSale = Math.random() > 0.5;

if (isFlashSale) {
    discount = 20;
}

// Lỗi: Variable 'discount' is used before being assigned.
console.log(discount);

Trong ví dụ trên, nếu isFlashSale là false, biến discount sẽ không có giá trị. TypeScript nhận thấy rủi ro này và chặn quá trình biên dịch để ngăn chặn sự cố tiềm ẩn khi thực thi (runtime).

Các nguyên nhân phổ biến

Hành vi này bắt nguồn từ "Phân tích luồng điều khiển" (Control Flow Analysis) của TypeScript. Bạn có thể gặp phải lỗi này trong một vài tình huống cụ thể:

  • Câu lệnh điều kiện thiếu: Bạn đã gán giá trị trong khối if nhưng quên khối else.
  • Khối Try-Catch: Biến được gán bên trong khối try, nhưng trình biên dịch lo ngại lỗi có thể xảy ra và nhảy sang khối catch trước khi việc gán giá trị hoàn tất.
  • Khởi tạo chậm: Biến được gán bên trong một callback hoặc một hàm lồng nhau có thể sẽ chạy sau đó.

Cách khắc phục

1. Cung cấp giá trị mặc định

Cách sửa đáng tin cậy nhất là khởi tạo biến ngay lập tức. Điều này đảm bảo biến luôn có một giá trị dự phòng hợp lệ, ngay cả khi logic của bạn không thực hiện cập nhật.

// Thay vì 'let role: string;', hãy sử dụng giá trị mặc định
let role: string = "guest";

if (user.isAdmin) {
    role = "admin";
}
console.log(role); // An toàn và sạch sẽ

2. Sử dụng Khẳng định gán chắc chắn (!)

Có những lúc bạn nắm rõ tình hình hơn trình biên dịch. Nếu bạn chắc chắn một biến sẽ được gán—chẳng hạn như thông qua một hook của framework hoặc hàm thiết lập—hãy thêm dấu ! sau tên biến khi khai báo. Điều này yêu cầu TypeScript tin tưởng vào quyết định của bạn.

let databaseUrl!: string;

function setup() {
    databaseUrl = "mongodb://localhost:27017";
}

setup();
console.log(databaseUrl.length); // Lỗi đã được loại bỏ

Mẹo chuyên nghiệp: Hãy sử dụng cách này một cách tiết kiệm. Nếu bạn phán đoán sai, ứng dụng sẽ ném ra lỗi TypeError khi chạy, điều này làm mất đi mục đích ban đầu của việc sử dụng TypeScript.

3. Khép kín luồng logic

Nếu bạn sử dụng câu lệnh if, hãy đảm bảo mọi nhánh rẽ có thể xảy ra đều thực hiện gán giá trị. Thêm một khối else thường là đủ để đáp ứng yêu cầu của trình biên dịch.

let status: string;

if (response.code === 200) {
    status = "Success";
} else {
    status = "Error"; // Mọi nhánh rẽ hiện đã được xử lý
}

console.log(status);

4. Tối ưu hóa với toán tử ba ngôi

Nếu logic của bạn đơn giản, đừng khai báo biến rồi mới gán sau. Thay vào đó, hãy sử dụng toán tử ba ngôi để khai báo và gán giá trị cùng lúc. Điều này cho phép bạn sử dụng const, một thực hành tốt hơn cho bộ nhớ và khả năng đọc mã.

// Sạch hơn và ngăn chặn hoàn toàn lỗi
const status = response.code === 200 ? "Success" : "Error";

5. Xử lý kịch bản Try-Catch

Khi làm việc với API, TypeScript giả định rằng khối try có thể thất bại. Để khắc phục, hãy đảm bảo biến cũng được gán trong khối catch hoặc được khởi tạo trước khi try bắt đầu.

let userData: User;

try {
    userData = await fetchUser();
} catch (err) {
    userData = { id: 0, name: "Anonymous" }; // Gán giá trị dự phòng
}

console.log(userData.name);

Cách kiểm tra kết quả

Kiểm tra tab "Problems" trong IDE của bạn hoặc chạy trình biên dịch thủ công từ terminal:

npx tsc --noEmit

Nếu terminal không trả về lỗi nào, bạn đã vượt qua các bước kiểm tra việc gán giá trị thành công. Bạn cũng nên chạy bộ test để đảm bảo rằng các giá trị mặc định mới không làm thay đổi hành vi mong đợi của ứng dụng.

Thực hành tốt nhất

  • Ưu tiên sử dụng const: Đặt mục tiêu sử dụng const cho 90% các biến của bạn. Nếu bạn không thể dùng const, đó thường là dấu hiệu cho thấy logic của bạn có thể được đơn giản hóa.
  • Đừng tắt chế độ strict: Bạn có thể muốn tắt strictNullChecks trong tsconfig.json để ẩn lỗi. Đừng làm vậy. Bạn chỉ đang đổi một cảnh báo khi biên dịch lấy một sự cố sập hệ thống vào giữa đêm.
  • Giữ mọi thứ đơn giản: Nếu logic gán giá trị của một biến kéo dài 50 dòng mã, trình biên dịch có thể sẽ gặp khó khăn. Hãy chia nhỏ logic phức tạp thành các hàm chuyên dụng nhỏ hơn.

Related Error Notes