TypeScript không chỉ đơn thuần là JavaScript kèm kiểu dữ liệu. Khi được sử dụng đúng cách, TypeScript giúp bạn xây dựng hệ thống lớn, dễ bảo trì, an toàn và mở rộng. Bài viết này tập trung vào các patterns nâng cao và best practices thực chiến, giúp bạn nâng tầm kỹ năng TypeScript.
1. Tư duy Type-First
❌ Sai lầm phổ biến
Viết JS trước, rồi thêm type cho có:
function process(data: any) {
return data.value * 2;
}
✅ Cách làm chuẩn
Thiết kế kiểu dữ liệu trước:
interface InputData {
value: number;
}
function process(data: InputData): number {
return data.value * 2;
}
👉 Tư duy type-first giúp:
-
Thiết kế API rõ ràng
-
Giảm bug runtime
-
Tăng khả năng refactor
2. Advanced Utility Types – Vũ khí tối thượng
2.1 Partial, Required, Readonly
interface User {
id: number;
name: string;
email: string;
}
type UpdateUser = Partial<User>;
type CreateUser = Required<Omit<User, 'id'>>;
type ImmutableUser = Readonly<User>;
2.2 Pick & Omit
type PublicUser = Pick<User, 'id' | 'name'>;
type PrivateUser = Omit<User, 'email'>;
2.3 Record – Map chuẩn type
type Role = 'admin' | 'user' | 'guest';
const permissions: Record<Role, string[]> = {
admin: ['create', 'update', 'delete'],
user: ['read'],
guest: ['read'],
};
3. Discriminated Union – Pattern xử lý logic cực mạnh
type Result =
| { status: 'success'; data: string }
| { status: 'error'; error: Error };
function handle(result: Result) {
if (result.status === 'success') {
console.log(result.data);
} else {
console.error(result.error);
}
}
👉 Ưu điểm:
-
Exhaustive checking
-
Không cần null check
-
Tránh logic bug
4. Exhaustive Check – Chặn bug từ compile time
function assertNever(x: never): never {
throw new Error('Unhandled case: ' + JSON.stringify(x));
}
function process(result: Result) {
switch (result.status) {
case 'success':
return result.data;
case 'error':
return result.error;
default:
return assertNever(result);
}
}
👉 Khi thêm type mới → TypeScript sẽ báo lỗi compile
5. Generic nâng cao – Viết code tái sử dụng cực gọn
5.1 Generic function
function identity<T>(value: T): T {
return value;
}
5.2 Generic constraint
function getId<T extends { id: number }>(obj: T): number {
return obj.id;
}
5.3 Generic + keyof
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
6. Type Narrowing nâng cao
6.1 in operator
function print(value: string | number | { name: string }) {
if ('name' in value) {
console.log(value.name);
}
}
6.2 Custom type guard
function isUser(x: any): x is User {
return typeof x?.id === 'number';
}
7. Immutable & Readonly Pattern
type DeepReadonly<T> = {
readonly [K in keyof T]: DeepReadonly<T[K]>;
};
👉 Áp dụng cực tốt trong:
-
Redux
-
Event sourcing
-
CQRS
8. Type vs Interface – Dùng thế nào cho đúng?
| Tiêu chí |
interface |
type |
| Extend |
extends |
intersection |
| Declaration merge |
Có |
Không |
| Union type |
❌ |
✅ |
| Advanced mapping |
❌ |
✅ |
👉 Best practice:
-
Dùng interface cho object public API
-
Dùng type cho union, mapping, utility
9. Clean Architecture + TypeScript
9.1 Domain Model
interface Order {
id: string;
total: number;
}
9.2 Use-case interface
interface CreateOrder {
execute(input: CreateOrderInput): Promise<Order>;
}
👉 Giúp:
-
Tách business logic
-
Dễ test
-
Dễ scale hệ thống
10. Zod + TypeScript – Runtime validation chuẩn chỉnh
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
11. Best Practices tổng hợp
✅ Nên làm
-
strict: true
-
noImplicitAny
-
exactOptionalPropertyTypes
-
Sử dụng ESLint + Prettier
-
Tránh any, ưu tiên unknown
❌ Tránh
12. Pattern thực tế: API Response chuẩn
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string };
Sử dụng:
async function fetchUser(): Promise<ApiResponse<User>> {
try {
return { success: true, data: await getUser() };
} catch (e) {
return { success: false, error: 'Fetch failed' };
}
}
13. Kết luận
TypeScript chỉ thực sự mạnh khi bạn:
Thiết kế type tốt hơn code.
Khi nắm vững:
-
Utility Types
-
Generic nâng cao
-
Discriminated Unions
-
Type narrowing
-
Exhaustive checking
bạn sẽ viết được hệ thống lớn, an toàn, dễ bảo trì và dễ scale.