Розширені типи TypeScript пояснюються на прикладах

TypeScript пропонує декілька розширених типів, які виходять за рамки базових типів, створюючи більш гнучкі та потужні системи типів. Ці вдосконалені типи допомагають створювати надійні програми, надаючи додаткові способи визначення та застосування обмежень типу. У цій статті на прикладах розглядаються деякі з цих розширених типів.

Типи спілок

Типи об’єднань дозволяють змінній бути одним із кількох типів. Це може бути корисно, коли значення може бути кількох типів, але його потрібно обробляти належним чином на основі його фактичного типу.

// 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));

У цьому прикладі функція `formatValue` приймає рядок або число та відповідно форматує значення.

Типи перехресть

Типи перетину поєднують кілька типів в один. Об'єкт типу перетину матиме всі властивості комбінованих типів. Це корисно для складання кількох типів разом.

// 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: "john.doe@example.com",
  phone: "123-456-7890"
};

console.log(employee);

Тут тип `Employee` є перетином `Person` і `Contact`, тобто він містить властивості обох інтерфейсів.

Літеральні типи

Літеральні типи вказують точні значення, які може містити змінна. Це може бути особливо корисним для забезпечення дозволеності лише певних конкретних значень.

// 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'.

Тип `Напрямок` тут обмежено чотирма конкретними значеннями рядка, гарантуючи, що лише ці напрямки можна використовувати у функції `переміщення`.

Типи кортежів

Типи кортежів представляють масив із фіксованою кількістю елементів, де кожен елемент може мати інший тип. Кортежі корисні для представлення колекцій різнорідних елементів фіксованого розміру.

// 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'.

Кортеж "користувач" визначається рядком, за яким слідує число, і цю структуру потрібно підтримувати.

Умовні типи

Умовні типи дозволяють визначати типи на основі умов. Вони забезпечують спосіб вибору того чи іншого типу на основі умови.

// Conditional type example

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

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

У цьому прикладі тип `IsString` перевіряє, чи є тип `T` рядком. Він повертає «Так», якщо так, і «Ні» в іншому випадку.

Відображені типи

Відображені типи дозволяють створювати нові типи шляхом перетворення властивостей існуючого типу. Це корисно для зміни або розширення існуючих типів.

// 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.

Тип `ReadonlyPerson` перетворює тип `Person`, роблячи всі його властивості лише для читання.

Висновок

Розширені типи TypeScript надають потужні інструменти для визначення вимог до складних типів і керування ними. Використовуючи типи об’єднання, перетину, літерали, кортежі, умовні та зіставлені типи, розробники можуть створювати більш надійні та придатні для обслуговування програми. Розуміння та ефективне застосування цих типів може значно підвищити безпеку типів і гнучкість коду TypeScript.