Расширенные типы 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);

Здесь тип «Сотрудник» является пересечением типов «Персона» и «Контакт», то есть он содержит свойства из обоих интерфейсов.

Типы литералов

Типы литералов указывают точные значения, которые может содержать переменная. Это может быть особенно полезно для обеспечения того, что разрешены только определенные конкретные значения.

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

Тип `Direction` здесь ограничен четырьмя конкретными строковыми значениями, что гарантирует, что в функции `move` могут использоваться только эти направления.

Типы кортежей

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

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

Кортеж `user` определяется строкой, за которой следует число, и эту структуру необходимо поддерживать.

Условные типы

Условные типы позволяют определять типы на основе условий. Они предоставляют способ выбора того или иного типа на основе условия.

// Conditional type example

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

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

В этом примере тип `IsString` проверяет, является ли тип `T` строкой. Он возвращает `"Yes"`, если это так, и `"No"` в противном случае.

Сопоставленные типы

Сопоставленные типы позволяют создавать новые типы путем преобразования свойств существующего типа. Это полезно для изменения или расширения существующих типов.

// 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 предоставляют мощные инструменты для определения и управления сложными требованиями к типам. Используя типы union, crossing, literal, tuple, conditional и mapped, разработчики могут создавать более надежные и поддерживаемые приложения. Понимание и эффективное применение этих типов может значительно повысить безопасность типов и гибкость кода TypeScript.