Giải thích các kiểu nâng cao của TypeScript bằng ví dụ

TypeScript cung cấp một số kiểu nâng cao vượt xa các kiểu cơ bản, cho phép các hệ thống kiểu linh hoạt và mạnh mẽ hơn. Các kiểu nâng cao này giúp tạo ra các ứng dụng mạnh mẽ bằng cách cung cấp các cách bổ sung để xác định và thực thi các ràng buộc kiểu. Bài viết này khám phá một số kiểu nâng cao này với các ví dụ.

Các loại công đoàn

Kiểu hợp nhất cho phép một biến có thể là một trong nhiều kiểu. Điều này có thể hữu ích khi một giá trị có thể có nhiều kiểu nhưng phải được xử lý phù hợp dựa trên kiểu thực tế của nó.

// Union type example

function formatValue(value: string | number): string {
  if (typeof value === 'string') {
    return `String: ${value}`;
  } else {
    return `Number: ${value.toFixed(2)}`;
  }
}

console.log(formatValue("Hello"));
console.log(formatValue(123.456));

Trong ví dụ này, hàm `formatValue` chấp nhận một chuỗi hoặc một số và định dạng giá trị cho phù hợp.

Các loại giao lộ

Kiểu giao nhau kết hợp nhiều kiểu thành một. Một đối tượng của kiểu giao nhau sẽ có tất cả các thuộc tính của các kiểu kết hợp. Điều này hữu ích khi kết hợp nhiều kiểu lại với nhau.

// Intersection type example

interface Person {
  name: string;
  age: number;
}

interface Contact {
  email: string;
  phone: string;
}

type Employee = Person & Contact;

const employee: Employee = {
  name: "John Doe",
  age: 30,
  email: "[email protected]",
  phone: "123-456-7890"
};

console.log(employee);

Tại đây, kiểu `Employee` là giao của `Person` và `Contact`, nghĩa là nó chứa các thuộc tính từ cả hai giao diện.

Các loại theo nghĩa đen

Kiểu dữ liệu theo nghĩa đen chỉ định các giá trị chính xác mà một biến có thể giữ. Điều này có thể đặc biệt hữu ích để đảm bảo rằng chỉ một số giá trị cụ thể nhất định được phép.

// Literal type example

type Direction = "up" | "down" | "left" | "right";

function move(direction: Direction): void {
  console.log(`Moving ${direction}`);
}

move("up");    // Valid
move("down");  // Valid
// move("side"); // Error: Argument of type '"side"' is not assignable to parameter of type 'Direction'.

Kiểu `Direction` ở đây bị giới hạn ở bốn giá trị chuỗi cụ thể, đảm bảo rằng chỉ những hướng này mới có thể được sử dụng trong hàm `move`.

Các loại Tuple

Kiểu Tuple biểu diễn một mảng có số lượng phần tử cố định, trong đó mỗi phần tử có thể có một kiểu khác nhau. Tuple hữu ích để biểu diễn các bộ sưu tập có kích thước cố định của các mục không đồng nhất.

// Tuple type example

let user: [string, number] = ["Alice", 30];

console.log(user[0]); // "Alice"
console.log(user[1]); // 30

// user = [30, "Alice"]; // Error: Type 'number' is not assignable to type 'string'.

Bộ `user` được định nghĩa bằng một chuỗi theo sau là một số và cấu trúc này phải được duy trì.

Các loại điều kiện

Các kiểu có điều kiện cho phép xác định các kiểu dựa trên các điều kiện. Chúng cung cấp một cách để chọn một kiểu này hay kiểu khác dựa trên một điều kiện.

// Conditional type example

type IsString = T extends string ? "Yes" : "No";

type Test1 = IsString;  // "Yes"
type Test2 = IsString;  // "No"

Trong ví dụ này, kiểu `IsString` kiểm tra xem kiểu `T` có phải là chuỗi không. Nó trả về `"Yes"` nếu đúng và `"No"` nếu không.

Các loại được ánh xạ

Các kiểu được ánh xạ cho phép tạo các kiểu mới bằng cách chuyển đổi các thuộc tính của kiểu hiện có. Điều này hữu ích cho việc sửa đổi hoặc mở rộng các kiểu hiện có.

// Mapped type example

type ReadonlyPerson = {
  readonly [K in keyof Person]: Person[K];
};

const readonlyPerson: ReadonlyPerson = {
  name: "Alice",
  age: 30
};

// readonlyPerson.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.

Kiểu `ReadonlyPerson` chuyển đổi kiểu `Person` bằng cách biến tất cả các thuộc tính của nó thành chỉ đọc.

Phần kết luận

Các kiểu nâng cao của TypeScript cung cấp các công cụ mạnh mẽ để xác định và quản lý các yêu cầu kiểu phức tạp. Bằng cách sử dụng các kiểu union, interfaces, literal, tuple, conditional và mapped, các nhà phát triển có thể tạo ra các ứng dụng mạnh mẽ và dễ bảo trì hơn. Hiểu và áp dụng các kiểu này một cách hiệu quả có thể cải thiện đáng kể tính an toàn và tính linh hoạt của kiểu mã TypeScript.