Back to Blog
TypeScript nâng cao: Patterns và Best Practices
TypeScript

TypeScript nâng cao: Patterns và Best Practices

Khám phá các patterns nâng cao trong TypeScript để viết code an toàn và dễ bảo trì hơn.

10 tháng 1, 2024
12 phút đọc

TypeScript nâng cao: Patterns và Best Practices

TypeScript đã trở thành một công cụ không thể thiếu trong phát triển JavaScript hiện đại. Hãy cùng khám phá các patterns nâng cao để viết code an toàn và dễ bảo trì hơn.

Generic Constraints

Generic constraints cho phép chúng ta giới hạn types có thể được sử dụng:

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

// Sử dụng
loggingIdentity("Hello"); // OK
loggingIdentity([1, 2, 3]); // OK
loggingIdentity(123); // Error: Argument of type 'number' is not assignable

Conditional Types

Conditional types cho phép tạo types dựa trên điều kiện:

type ApiResponse<T> = T extends string 
  ? { message: T } 
  : { data: T };

type StringResponse = ApiResponse<string>; // { message: string }
type NumberResponse = ApiResponse<number>; // { data: number }

Mapped Types

Mapped types giúp tạo types mới từ types hiện có:

type Partial<T> = {
  [P in keyof T]?: T[P];
}

type Required<T> = {
  [P in keyof T]-?: T[P];
}

interface User {
  id: number;
  name: string;
  email?: string;
}

type PartialUser = Partial<User>; // Tất cả properties đều optional
type RequiredUser = Required<User>; // Tất cả properties đều required

Template Literal Types

Template literal types cho phép tạo string types động:

type EventName<T extends string> = `on${Capitalize<T>}`;

type ClickEvent = EventName<"click">; // "onClick"
type HoverEvent = EventName<"hover">; // "onHover"

// Sử dụng trong function
function addEventListener<T extends string>(
  event: EventName<T>,
  handler: () => void
) {
  // Implementation
}

addEventListener("onClick", () => {}); // OK
addEventListener("onHover", () => {}); // OK

Utility Types nâng cao

Pick và Omit

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
}

type PublicUser = Pick<User, 'id' | 'name' | 'email'>;
type UserWithoutPassword = Omit<User, 'password'>;

Record Type

type Status = 'pending' | 'approved' | 'rejected';

type StatusConfig = Record<Status, {
  color: string;
  message: string;
}>;

const statusConfig: StatusConfig = {
  pending: { color: 'yellow', message: 'Đang chờ xử lý' },
  approved: { color: 'green', message: 'Đã phê duyệt' },
  rejected: { color: 'red', message: 'Đã từ chối' }
};

Best Practices

1. Sử dụng strict mode

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

2. Tránh any type

// ❌ Tránh
function processData(data: any) {
  return data.someProperty;
}

// ✅ Tốt hơn
function processData<T extends { someProperty: unknown }>(data: T) {
  return data.someProperty;
}

3. Sử dụng Type Guards

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

function processValue(value: unknown) {
  if (isString(value)) {
    // TypeScript biết value là string ở đây
    console.log(value.toUpperCase());
  }
}

Kết luận

Những patterns này giúp code TypeScript của bạn trở nên mạnh mẽ, an toàn và dễ bảo trì hơn. Việc nắm vững các concepts này sẽ giúp bạn viết code chất lượng cao và tận dụng tối đa sức mạnh của TypeScript.


Tags: TypeScript, JavaScript, Programming, Best Practices, Advanced

Tags:

TypeScript
JavaScript
Programming
Best Practices
Advanced