Utility Types trong TS | TypeScript Series
Utility Types là gì?
Utility types là những kiểu được dựng sẵn trong TypeScript để giúp biến đổi, chuyển đổi các kiểu dữ liệu khác dễ dàng hơn — thay vì viết lại toàn bộ kiểu từ đầu.

Các Utility Types phổ biến & cách dùng
1. Partial<T>
Khi bạn dùng Partial<T> với kiểu T, mọi thuộc tính của T sẽ trở thành tùy chọn (optional).
Ví dụ:
interface Point {
x: number;
y: number;
}
let pointPart: Partial<Point> = {}; // x và y đều không bắt buộc
pointPart.x = 10;
Khi dùng: Khi bạn chỉ cần cung cấp một phần dữ liệu — ví dụ cập nhật một phần object, hoặc constructor nhận dữ liệu “rời rạc”.
2. Required<T>
Ngược lại với Partial<T>, Required<T> biến mọi thuộc tính của T thành bắt buộc (required) — kể cả những thuộc tính vốn có dấu ?.
Ví dụ:
interface Car {
make: string;
model: string;
mileage?: number;
}
let myCar: Required<Car> = {
make: 'Ford',
model: 'Focus',
mileage: 12000 // mileage giờ bắt buộc có
};
Khi dùng: Khi bạn muốn đảm bảo rằng object nào đó “hoàn chỉnh” — không thiếu bất cứ thuộc tính nào.
3. Record<K, T>
Record<K, T> tạo một kiểu object mà key của nó nằm trong kiểu K và value của mỗi key nằm trong kiểu T.
Ví dụ:
const nameAgeMap: Record<string, number> = {
'Alice': 21,
'Bob': 25
};
// Tương đương với: { [key: string]: number }
Khi dùng: Khi bạn muốn tạo map/dictionary với key và value kiểu rõ ràng — ví dụ mapping tên người → tuổi, id → data object, v.v.
4. Omit<T, K>
Omit<T, K> tạo kiểu mới từ T nhưng loại bỏ đi những thuộc tính trong K (một hoặc nhiều key).
Ví dụ:
interface Person {
name: string;
age: number;
location?: string;
}
const bob: Omit<Person, 'age' | 'location'> = {
name: 'Bob'
// age và location không được khai!
};
Khi dùng: Khi bạn có interface lớn nhưng trong ngữ cảnh nào đó chỉ muốn sử dụng “một phần” của nó và loại bỏ những trường không cần.
5. Pick<T, K>
Tạo một kiểu mới chỉ bao gồm một số thuộc tính (được chọn) từ kiểu gốc T.
Cú pháp:
Pick<Type, Keys>
Type: kiểu gốcKeys: tên thuộc tính (hoặc tập hợp tên) bạn muốn giữ lại
Ví dụ:
interface Person {
name: string;
age: number;
location: string;
}
type PersonNameAndAge = Pick<Person, "name" | "age">;
const user: PersonNameAndAge = {
name: "Alice",
age: 25
// location bị loại bỏ
};
Khi dùng:
Khi bạn chỉ muốn lấy một vài thuộc tính cụ thể từ một kiểu lớn hơn — ví dụ chỉ lấy “name” và “age” từ Person.
6. Readonly<T>
Biến tất cả thuộc tính của T thành chỉ đọc (không thể gán lại giá trị).
Cú pháp:
Readonly<Type>
Ví dụ:
interface Book {
title: string;
author: string;
}
const myBook: Readonly<Book> = {
title: "Atomic Habits",
author: "James Clear"
};
// myBook.title = "Other"; ❌ lỗi – không thể gán lại
Khi dùng:
Khi bạn muốn bảo vệ dữ liệu không bị thay đổi sau khi khởi tạo (tương tự như const cho object).
7. Exclude<T, U>
Tạo kiểu mới loại bỏ các kiểu trong U ra khỏi T.
Cú pháp:
Exclude<Type, ExcludedUnion>
Ví dụ:
type Primitive = string | number | boolean;
type WithoutBoolean = Exclude<Primitive, boolean>;
// Kết quả: string | number
Khi dùng: Khi bạn muốn loại bỏ một hoặc nhiều kiểu cụ thể khỏi union type.
8. Extract<T, U>
Ngược lại với Exclude — nó giữ lại các kiểu trong T mà trùng với U.
Cú pháp:
Extract<Type, Union>
Ví dụ:
type Mixed = string | number | boolean;
type OnlyStringOrNumber = Extract<Mixed, string | number>;
// Kết quả: string | number
Khi dùng: Khi bạn chỉ muốn giữ lại kiểu có trong tập hợp nào đó.
9. NonNullable<T>
Tạo kiểu mới từ T nhưng loại bỏ null và undefined.
Cú pháp:
NonNullable<Type>
Ví dụ:
type PossibleValues = string | number | null | undefined;
type CleanValues = NonNullable<PossibleValues>;
// Kết quả: string | number
Khi dùng: Khi bạn chắc chắn rằng dữ liệu sẽ không bao giờ là null hoặc undefined, và muốn TypeScript bắt lỗi nếu có trường hợp đó.
Tổng hợp nhanh
| Utility Type | Tác dụng | Ví dụ ngắn |
|---|---|---|
| Pick<T, K> | Chọn một số thuộc tính từ kiểu T |
`Pick<Person, "name" |
| Readonly<T> | Biến toàn bộ thuộc tính thành chỉ đọc | Readonly<Book> |
| Exclude<T, U> | Loại bỏ các kiểu trong U khỏi T |
`Exclude<string |
| Extract<T, U> | Giữ lại các kiểu trong T mà có trong U |
`Extract<string |
| NonNullable<T> | Loại bỏ null và undefined khỏi T |
`NonNullable<string |
Mẹo ghi nhớ nhanh
| Mục tiêu | Utility nên dùng |
|---|---|
| Chỉ lấy vài field trong object | Pick |
| Loại bỏ vài field | Omit |
| Cho phép bỏ qua field | Partial |
| Bắt buộc tất cả field | Required |
| Chống sửa đổi field | Readonly |
| Loại bỏ kiểu không mong muốn | Exclude |
| Giữ lại kiểu mong muốn | Extract |
| Loại bỏ null/undefined | NonNullable |
Tóm lại
- Utility types giúp giảm lập lại trong việc khai kiểu, đồng thời giữ được an toàn kiểu (type-safety).
- Khi viết module, interface hoặc API response, hãy nghĩ tới việc “liệu có cần bản sao kiểu mà tất cả field optional / bỏ bớt field / kiểu map … không” → nếu có thì dùng
Partial,Omit,Record, v.v. - Không nên dùng “một cách tùy tiện” mà không hiểu vì sao — vì sử dụng sai có thể làm kiểu dữ liệu mơ hồ, dẫn tới lỗi logic hoặc mất lợi ích kiểm tra kiểu.
All rights reserved