22 tháng 3, 2026 · 12 phút đọc

TypeScript Generics thực chiến: pattern nào dùng khi nào

Từ generic functions cơ bản đến conditional types, mapped types và template literal types — hướng dẫn thực tế với các use case thật.

TypeScript Generics thực chiến: pattern nào dùng khi nào

TypeScript Generics là một trong những tính năng mạnh nhất và cũng khó nhất của ngôn ngữ. Nhiều developer tránh dùng vì cú pháp phức tạp — nhưng khi hiểu đúng, generics giúp viết code type-safe mà không phải duplicate logic.

Generic Functions: bắt đầu từ identity

Hàm identity đơn giản nhất: function identity<T>(value: T): T { return value; }. TypeScript suy luận T từ argument — bạn không cần khai báo type khi gọi. Đây là nền tảng để hiểu type inference hoạt động như thế nào.

Use case thực tế: wrapper function cho API calls. Thay vì viết fetchUser(), fetchProduct() riêng biệt, viết một hàm fetch<T>(url: string): Promise<T> dùng được với mọi resource type.

TypeScript code on screen
Generic constraints giúp TypeScript inference chính xác hơn

Constraints với extends

T extends object nghĩa là T phải là subtype của object. T extends keyof U ràng buộc T phải là một property key của U. Đây là nền tảng cho pattern Pick, Omit, và rất nhiều utility types trong codebase thực.

Một pattern hay: function getProperty<T, K extends keyof T>(obj: T, key: K): T[K]. Hàm này type-safe hoàn toàn — return type là chính xác type của property đó, không phải any.

Conditional Types

T extends U ? X : Y — conditional type hoạt động như ternary ở type level. Dùng khi bạn muốn return type phụ thuộc vào input type. Ví dụ: IsArray<T> = T extends any[] ? true : false.

infer keyword dùng trong conditional types để 'extract' type từ type phức tạp. Ví dụ: ReturnType<T> = T extends (...args: any[]) => infer R ? R : never — đây chính là cách TypeScript implement utility type ReturnType.

Mapped Types

{ [K in keyof T]: ... } cho phép transform tất cả properties của một type. Partial<T>, Required<T>, Readonly<T> đều được implement bằng mapped types. Bạn có thể thêm hoặc bỏ modifiers (? và readonly) bằng + và - prefix.

Template Literal Types

Kể từ TypeScript 4.1, bạn có thể dùng template literal syntax ở type level: type EventName<T extends string> = `on${Capitalize<T>}`. Kết hợp với mapped types và conditional types, đây là công cụ cực mạnh cho type-safe event systems và API builders.

Khi nào nên dùng: khi bạn thấy mình phải maintain nhiều overloads tương tự, hoặc khi cần type-safety cho string patterns như CSS properties, event names, hoặc route paths.