Mục lục

Meta-programming: Mapped & Template Literals

Sử dụng sức mạnh của TypeScript để tự động hóa việc tạo Type cho Design Systems phức tạp.

Trong các dự án Design System, bạn thường phải đối mặt với hàng trăm biến thể (Colors, Spacing, Buttons). Thay vì viết tay từng Type, Senior Engineer sử dụng Meta-programming để tạo ra các Type linh hoạt và tự động.

1. Mapped Types: Lập trình trên Object

Mapped Types cho phép bạn duyệt qua một tập hợp các key để tạo ra Type mới.

typescript:
type Colors = 'primary' | 'secondary' | 'accent';

// Tự động tạo Type cho các biến thể Tailwind/CSS
type ColorTokens = {
  [K in Colors]: string;
};

// Kết quả: { primary: string; secondary: string; accent: string; }

Kết hợp với Modifiers, bạn có thể biến các thuộc tính thành readonly hoặc optional một cách đồng loạt:

typescript:
type ReadonlyColors<T> = {
  readonly [K in keyof T]: T[K];
};

2. Template Literal Types: Ghép chuỗi thông minh

Đây là tính năng "thần thánh" giúp TS hiểu được logic của các chuỗi text phức tạp.

typescript:
type Size = 'sm' | 'md' | 'lg';
type Status = 'hover' | 'active' | 'disabled';

// Tự động tạo ra 9 Class name cho Button
type ButtonClasses = `btn-${Size}-${Status}`;

// Kết quả: "btn-sm-hover" | "btn-sm-active" | ... | "btn-lg-disabled"

Ứng dụng thực tế: Deep Property Access

Giả sử bạn có một hàm get() để lấy dữ liệu từ một object lồng nhau theo đường dẫn user.address.street:

typescript:
function get<T, K extends string>(obj: T, path: K): any { ... }

// Làm sao để TS gợi ý được "address.street"? 
// Đó là lúc chúng ta cần Meta-programming đỉnh cao.

3. Conditional Types & kỹ thuật infer

Conditional Types cho phép bạn viết logic if-else ngay trong Type.

typescript:
type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false

Kỹ thuật infer giúp "trích xuất" thông tin từ một Type phức tạp (ví dụ: lấy kiểu dữ liệu trả về của một Function):

Lab: Trích xuất Type với infer

Hãy chạy bài Lab sau để thấy cách infer "nhìn xuyên" qua một Function để lấy được kiểu dữ liệu mà nó trả về hoặc kiểu của các tham số đầu vào.

4. Tại sao đây là kiến thức Senior?

Việc lạm dụng Meta-programming có thể làm TypeScript Compiler chạy chậm và khiến code khó đọc. Một Senior Engineer phải biết:

  • Khi nào nên dùng: Khi xây dựng Design System nền tảng, các thư viện dùng chung cho cả team.
  • Khi nào nên tránh: Trong các logic nghiệp vụ đơn giản, dễ thay đổi.

Làm chủ được Meta-programming giúp bạn xây dựng những hệ thống "Type-safe by design" - nơi mà lỗi hầu như không thể xảy ra vì Type đã bao phủ mọi trường hợp logic.

Quảng cáo
mdhorizontal