TypeScript đã trở thành tiêu chuẩn ngành cho phát triển web quy mô lớn. Mặc dù hầu hết các lập trình viên đều biết các kiến thức cơ bản về interface và type, sức mạnh thực sự nằm ở hệ thống type nâng cao. Dưới đây là 5 mẫu sẽ giúp bạn nổi bật với tư cách là một kỹ sư cao cấp.
1. Generic Constraints
Generics rất mạnh mẽ, nhưng đôi khi bạn cần giới hạn những gì có thể được truyền vào. extends là người bạn đồng hành của bạn ở đây.
interface HasId { id: string; } function getById<T extends HasId>(list: T[], id: string): T | undefined { return list.find((item) => item.id === id); }
Bằng cách đảm bảo T kế thừa HasId, chúng ta đảm bảo rằng việc truy cập .id bên trong hàm là an toàn.
2. Conditional Types
Conditional types cho phép bạn tạo các ánh xạ type không đồng nhất. Cú pháp tương tự như toán tử ba ngôi trong JavaScript.
type IsString<T> = T extends string ? true : false; type A = IsString<string>; // true type B = IsString<number>; // false
Một trường hợp sử dụng thực tế là lọc các type từ một union:
type Diff<T, U> = T extends U ? never : T; type NonNullable<T> = Diff<T, null | undefined>;
3. Mapped Types
Mapped types cho phép bạn tạo các type mới dựa trên các type cũ bằng cách biến đổi các thuộc tính.
type ReadOnly<T> = { readonly [P in keyof T]: T[P]; }; interface User { name: string; age: number; } type ReadOnlyUser = ReadOnly<User>;
Bạn thậm chí có thể thêm hoặc xóa các modifier:
type Mutable<T> = { -readonly [P in keyof T]: T[P]; };
4. Template Literal Types
Được giới thiệu trong TypeScript 4.1, chúng cho phép bạn thao tác trực tiếp với các kiểu chuỗi.
type World = 'world'; type Greeting = `hello ${World}`; // "hello world" type Color = 'red' | 'blue'; type Quantity = 'light' | 'dark'; type Palette = `${Quantity}-${Color}`; // "light-red" | "light-blue" | "dark-red" | "dark-blue"
Điều này cực kỳ hữu ích để định kiểu cho các chuỗi tuân theo một mẫu cụ thể, như các lớp CSS hoặc tên sự kiện.
5. Từ khóa infer
Từ khóa infer trong conditional types cho phép bạn trích xuất type từ các type khác.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any; function check(): boolean { return true; } type CheckReturn = ReturnType<typeof check>; // boolean
Ở đây, chúng ta yêu cầu TypeScript "suy luận" kiểu trả về R của một hàm và trả về nó.
Kết luận
Thành thạo các mẫu này cho phép bạn viết các thư viện và tiện ích mạnh mẽ, mang lại trải nghiệm phát triển (DX) tuyệt vời. Mục tiêu của TypeScript nâng cao không phải là sự phức tạp vì sự phức tạp, mà là sự an toàn và khả năng biểu đạt.