Generics là core feature trong các statically-typed languages như TypeScript, cho phép developers define các components, functions, hoặc structures có thể accept và enforce các types được truyền vào khi sử dụng. Điều này tăng cường flexibility, thúc đẩy reusability, và giảm code duplication.
Trong bài hướng dẫn này, chúng ta sẽ khám phá các ví dụ thực tế về TypeScript generics và học cách sử dụng chúng hiệu quả trong functions, types, classes, và interfaces để cải thiện type safety và adaptability trong code của bạn.
Yêu cầu
Nội dung bài hướng dẫn
6 phần • khoảng 1 giờ
Generics trong TypeScript cho phép các developer tạo code có thể tái sử dụng và thích ứng trong khi vẫn duy trì type safety nghiêm ngặt. Bằng cách cho phép truyền types như tham số, generics giúp xây dựng các cấu trúc và hàm có thể xử lý các kiểu dữ liệu cụ thể, mà không phải hy sinh lợi ích của static typing trong TypeScript.
Trong TypeScript, generics được biểu diễn bằng dấu ngoặc nhọn như <T>, trong đó T đại diện cho kiểu được truyền vào.
Ký hiệu này hoạt động tương tự như tham số hàm, đóng vai trò như placeholder cho một kiểu sẽ được chỉ định khi cấu trúc được khởi tạo.
1. Truyền tham số kiểu vào type, interface, class
Type aliases có thể sử dụng generics để tạo các kiểu linh hoạt và có thể tái sử dụng.
Interfaces cũng có thể nhận tham số generic, cho phép các contracts cụ thể và có thể tái sử dụng hơn.
Classes có thể nhận generic types để định nghĩa properties và methods với xử lý kiểu linh hoạt.
2. Truyền tham số kiểu vào function
Functions có thể nhận tham số generic để làm việc với các kiểu khác nhau một cách động.
3. Truyền tham số kiểu vào React components
React components cũng có thể nhận tham số generic để định nghĩa kiểu của props mà chúng nhận.
Trong React, chúng ta thường không cần truyền kiểu tường minh vào component, vì hầu hết trường hợp, kiểu có thể được suy luận từ props mà chúng ta truyền vào component. Và đây cũng là thực hành tốt để trình biên dịch TS suy luận kiểu cho bạn, vì nó làm code của bạn sạch hơn và dễ đọc hơn.
Chia sẻ với mọi người
Về tác giả
NAB, Lead Engineer
Mình là Vũ, hiện là Lead Engineer ở NAB (National Australia Bank). Mình bắt đầu ở mảng Home Lending, giờ đang lead một team làm sản phẩm cho HICAPS, dịch vụ point-of-sale claiming bảo hiểm sức khỏe tư nhân lớn nhất ở Úc. Trước NAB, mình từng làm ở các startup và nhiều team khác với đa dạng stack.
Upskills là nơi mình chia sẻ những kiến thức thực tế từ công việc, để giúp bạn build và ship dự án tốt hơn. Ngoài tutorial, sắp tới sẽ có thêm nhiều nội dung: project showcase, interview prep, và các AI tool, như những resource cho hành trình học của bạn. Mình rất vui được chia sẻ những kiến thức và kinh nghiệm đã học được trong suốt quá trình làm việc, và có thể chia sẻ thêm nhiều điều thú vị cùng nhau khi chúng ta tiếp tục build những thứ hay ho.
Các bài deep-dive về web development thực tế, một đến hai tuần một số, viết bởi engineer thực sự có kinh nghiệm build sản phẩm. Không sáo rỗng, không câu view.
Chúng tôi tôn trọng quyền riêng tư. Hủy đăng ký bất cứ lúc nào.
class MyStorage<T> {private items: T[] = [];addItem(item: T): void {this.items.push(item);}getAllItems(): T[] {return this.items;}
type ApiResponse<T> = {// ^?data: T;status: number;error?: string;};// Cách sử dụngtype User = { id: number; name: string };
interface KeyValuePair<K, V> {key: K;value: V;}// Cách sử dụngconst stringPair: KeyValuePair<string, string> = { key: "name", value: "Alice" };const numberPair: KeyValuePair<number, boolean>
class MyStorage<T> {private items: T[] = [];addItem(item: T): void {this.items.push(item);}getAllItems(): T[] {return this.items;
function createKeyValueStore<K, V>() {return new Map<K, V>();}const userAges = createKeyValueStore<string, number>();// ^?userAges.set("Alice", 28
type DropdownProps<T> = {items: T[];getLabel: (item: T) => string;onSelect: (item: T) =>