Mục lục

Discriminated Unions: Quản lý State tuyệt đối an toàn

Kỹ thuật tối thượng để xử lý các trạng thái phức tạp trong ứng dụng lớn mà không bao giờ gặp lỗi undefined.

Trong các ứng dụng quy mô lớn, việc quản lý State là nơi phát sinh nhiều lỗi nhất. Senior TS Engineer sử dụng Discriminated Unions (hoặc Tagged Unions) để đảm bảo trình biên dịch (Compiler) luôn hiểu rõ trạng thái hiện tại là gì.

1. Vấn đề của cách làm thông thường

Nếu bạn thiết kế một interface chứa tất cả các thuộc tính "có thể có":

typescript:
interface NetworkState {
  status: 'loading' | 'success' | 'error';
  data?: string;
  error?: string;
}

Khi status === 'success', bạn vẫn phải check if (state.data) vì nó là dấu ?. Đây là nguồn gốc của lỗi logic.

2. Giải pháp: Phân biệt bằng "Discriminant"

Chúng ta tách nhỏ interface và sử dụng một thuộc tính chung làm "nhãn" (Tag).

typescript:
interface LoadingState {
  type: 'loading';
}

interface SuccessState {
  type: 'success';
  data: string;
}

interface ErrorState {
  type: 'error';
  message: string;
}

type State = LoadingState | SuccessState | ErrorState;

3. Lab: Sức mạnh của Exhaustiveness Checking

Hãy chạy bài Lab sau để thấy TS "thông minh" như thế nào khi bạn dùng switch/case.

4. Tại sao đây là Senior Pattern?

  1. Chống lỗi Runtime: Bạn không thể truy cập action.user nếu type đang là LOGOUT.
  2. Tự động cập nhật: Nếu bạn thêm một type mới vào Action mà quên xử lý trong switch/case, TS sẽ báo lỗi ngay lập tức tại dòng _exhaustiveCheck (vì never không thể gán bằng type mới).
  3. Hỗ trợ Refactoring: Khi thay đổi cấu trúc của một trạng thái, TS sẽ chỉ ra chính xác mọi nơi cần sửa chữa trong toàn bộ dự án.

So với cách làm của JavaScript thuần (phải unit test cực kỳ nhiều để đảm bảo an toàn), Discriminated Unions giúp bạn "xây dựng sự an toàn" ngay từ lớp định nghĩa dữ liệu.

Quảng cáo
mdhorizontal