TypeScript satisfies — Cái 'công tắc' mà hồi đó mình ước có

Phong

Chào mấy bạn,

Mấy bữa nay mình đang refactor lại cái codebase TypeScript cũ ở công ty, tự dưng nhớ lại hồi xưa cứ phải loay hoay với cái type annotation trong TS. Có một thằng mình muốn giới thiệu với mấy bạn hôm nay — cái satisfies operator. Nghe tên hơi lạ, nhưng dùng hoài luôn.

Laptop và workspace quen thuộc mỗi ngày Ảnh: Lukas Blazek — Pexels

Tại sao mình cần nó?

Giả sử bạn có một object config kiểu:

const config = {
  api: 'https://api.example.com',
  timeout: 5000,
  retry: true,
} satisfies Record<string, string | number | boolean>;

Hồi xưa nếu dùng Record thì mất hết type cụ thể của từng property. Còn satisfies vừa kiểm tra đúng shape, vừa giữ nguyên type chính xác — config.apistring, config.timeoutnumber. Hai bên đều vui.

Hay có một ví dụ khác mà mình gặp hoài:

type Color = 'red' | 'green' | 'blue';
type ColorMap = Record<string, Color>;

const palette = {
  primary: 'red',
  secondary: 'green',
  warning: 'blue',
} satisfies ColorMap;

Đây là cái hay: vừa được inference chi tiết cho từng key, vừa không bỏ sót lỗi kiểu dữ liệu. Cú pháp nhẹ nhàng, nhưng hiệu quả bất ngờ.

Sách với kiến thức công nghệ Ảnh: Sarah — Pexels

Khi nào nên xài?

Mình thấy satisfies hợp nhất khi bạn muốn:

  • Kiểm tra một object với một type tổng quát, nhưng vẫn cần autocomplete cho từng field
  • Đảm bảo object đúng interface nào đó (VD: ZodSchema, AxiosConfig) mà không muốn đánh mất type chi tiết
  • Kết hợp với Record, Map, hay generic type

Nói chung, nếu mấy bạn đang xài TypeScript 4.9+ và chưa thử satisfies thì hãy dành 5 phút chơi thử. Mình cá là các bạn sẽ thích à.

Chúc mọi người code vui vẻ! ✨