TypeScript satisfies — khi type safety gặp trải nghiệm dev
Mở đầu
Hồi mới chuyển từ JavaScript qua TypeScript, mình đau đầu nhất là cái vụ: muốn type safety nhưng đừng làm mất tính linh hoạt của giá trị gốc. Có những biến mình muốn nó thoả mãn một type nào đó, nhưng lại cần TypeScript suy luận (infer) đúng kiểu cụ thể — chứ không phải cái type rộng hơn.
Nghe kỹ thuật quá ha? Để mình kể chuyện cho dễ.
Ảnh: Lukas Blazek — Pexels
Vấn đề
Giả sử mình có config cho HTTP methods:
const config = {
GET: "read-only",
POST: "write",
DELETE: true
};
Mình muốn config có type là Record<string, string | boolean>, nhưng vẫn nhớ được literal type của từng key — "GET", "POST", "DELETE" — để IDE gợi ý khi gọi config.GET.
Cách cũ: ghi type annotation — được checking nhưng mất autocomplete cho key cụ thể. Không ghi type — được autocomplete nhưng mất safety. Đau đầu thiệt sự.
satisfies — giải pháp
TypeScript 4.9 giới thiệu toán tử satisfies. Nó kiểm tra type mà không thay đổi suy luận:
const config = {
GET: "read-only",
POST: "write",
DELETE: true
} satisfies Record<string, string | boolean>;
Nếu mình viết sai kiểu (ví dụ GET: 123), nó báo lỗi. Nhưng TypeScript vẫn infer config là { GET: string; POST: string; DELETE: boolean } — literal types được giữ nguyên. config.GET trả về string (chứ không phải string | boolean), và IDE gợi ý đúng 3 keys.
Ảnh: ThisIsEngineering — Pexels
Cảm nhận của mình
Thiệt tình là satisfies giải quyết đúng cái pain point mình gặp hoài. Trước đây mình hay phải chọn giữa "chuẩn" (type annotation) và "tiện" (inference). Giờ có cả hai.
Một ví dụ khác: map màu cho theme:
const buttonColors = {
primary: "#3b82f6",
success: "#10b981",
danger: "#ef4444"
} satisfies Record<string, `#${string}`>;
Đảm bảo tất cả giá trị đều là hex color, nhưng autocomplete vẫn gợi ý buttonColors.primary — không phải buttonColors[0].
Nói chung, satisfies là tính năng mình xài hằng ngày. Nó không phải thứ "wow" kiểu decorator, nhưng nó làm code sạch hơn, an toàn hơn, và — quan trọng nhất — không làm phiền trải nghiệm dev. Còn bạn, có tính năng TypeScript nào làm bạn thay đổi cách code không? Comment cho mình biết nha!
📋 Phụ lục thuật ngữ
- satisfies — toán tử kiểm tra type, vừa type safety vừa giữ nguyên literal type inference
- Literal type — kiểu cụ thể, VD: "hello" thay vì string
- Record<K, V> — utility type cho object với keys loại K và values loại V
- Template literal type — type dùng template literal, VD: `#${string}` là string bắt đầu bằng #