JavaRush /Курсы /Модуль 2: Fullstack /Union и Intersection Types

Union и Intersection Types

Модуль 2: Fullstack
4 уровень , 6 лекция
Открыта

7.1 Union Types (Типы объединений)

В TypeScript есть довольно-таки редкая вещь — Union и Intersection Types. Это возможность создавать новые типы в виде выражений из других типов. Эти «типы» позволяют создавать сложные и многогранные типовые структуры, обеспечивая высокую степень гибкости и контроля над типизацией.

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

Синтаксис

Union Types создаются с использованием символа вертикальной черты |, который указывает, что переменная может иметь значение одного из перечисленных типов.

    
      let name: type1 | type2 | ...;
    
  

Пример:

TypeScript
    
      let value: string | number;
      value = 'Hello';
      value = 42;
      value = true; // Ошибка компиляции: Type 'boolean' is not assignable to type 'string | number'.
    
  

В этом примере переменная value может принимать значения типа string или number, но не типа boolean.

Применение Union Types в функциях

Union Types особенно полезны в функциях, которые могут принимать параметры нескольких типов.

Пример:

JavaScript
    
      "use strict";
      function printId(id) {
        console.log(`ID: ${id}`);
      }
      printId('abc123'); // Вывод: ID: abc123
      printId(123); // Вывод: ID: 123
    
  
TypeScript
    
      function printId(id: string | number): void {
        console.log(`ID: ${id}`);
      }

      printId('abc123'); // Вывод: ID: abc123
      printId(123); // Вывод: ID: 123
    
  

В этом примере функция printId принимает параметр id, который может быть либо строкой, либо числом.

Сужение типов (Type Narrowing)

Когда вы работаете с Union Types, TypeScript автоматически выполняет сужение типов (Type Narrowing), чтобы определить конкретный тип переменной в определенном контексте.

Пример:

JavaScript
    
      "use strict";
      function formatValue(value) {
          if (typeof value === 'string') {
              return value.toUpperCase(); //TypeScript компилятор знает, что value тут это строка
          }
          else {
              return value.toFixed(2); //TypeScript компилятор знает, что value тут это число
          }
      }
      console.log(formatValue('hello')); // Вывод: HELLO
      console.log(formatValue(123.456)); // Вывод: 123.46
    
  
TypeScript
    
      function formatValue(value: string | number): string {
        if (typeof value === 'string') {
          return value.toUpperCase(); //TypeScript компилятор знает, что value тут это строка
        } else {
          return value.toFixed(2); //TypeScript компилятор знает, что value тут это число
        }
      }

      console.log(formatValue('hello')); // Вывод: HELLO
      console.log(formatValue(123.456)); // Вывод: 123.46
    
  

В этом примере TypeScript использует оператор typeof, чтобы определить, является ли value строкой или числом, и применяет соответствующие методы.

7.2 Intersection Types (Типы пересечений)

Intersection Types позволяют объединять несколько типов в один, требуя, чтобы переменная соответствовала всем указанным типам. Это полезно, когда вы хотите создать новый тип, который объединяет свойства нескольких других типов.

Синтаксис

Intersection Types создаются с использованием символа амперсанда "&", который указывает, что переменная должна удовлетворять всем перечисленным типам:

    
      let name: type1 & type2 & ...;
    
  

Пример:

JavaScript
    
      "use strict";
      let staff = {
        name: 'Alice',
        age: 30,
        employeeId: 12345,
        position: 'Manager'
      };
      console.log(staff);
    
  
TypeScript
    
      interface Person {
        name: string;
        age: number;
      }

      interface Employee {
        employeeId: number;
        position: string;
      }

      type StaffMember = Person & Employee;

      let staff: StaffMember = {
        name: 'Alice',
        age: 30,
        employeeId: 12345,
        position: 'Manager'
      };

      console.log(staff);
    
  

В этом примере тип StaffMember является пересечением типов Person и Employee, и объект staff должен иметь свойства обоих этих типов.

Применение Intersection Types в функциях

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

Пример:

JavaScript
    
      "use strict";
      function getEmployeeDetails(employee) {
        return `${employee.name}, Age: ${employee.age}, ID: ${employee.employeeId}, Position: ${employee.position}`;
      }
      let employee = {
        name: 'Bob',
        age: 25,
        employeeId: 67890,
        position: 'Developer'
      };
      console.log(getEmployeeDetails(employee)); // Вывод: Bob, Age: 25, ID: 67890, Position: Developer
    
  
TypeScript
    
      function getEmployeeDetails(employee: Person & Employee): string {
        return `${employee.name}, Age: ${employee.age}, ID: ${employee.employeeId}, Position: ${employee.position}`;
      }

      let employee: Person & Employee = {
        name: 'Bob',
        age: 25,
        employeeId: 67890,
        position: 'Developer'
      };

      console.log(getEmployeeDetails(employee)); // Вывод: Bob, Age: 25, ID: 67890, Position: Developer
    
  

В этом примере функция getEmployeeDetails принимает параметр employee, который должен соответствовать как типу Person, так и типу Employee.

Преимущества использования Union и Intersection Types

  • Гибкость: Union Types позволяют функции принимать аргументы различных типов, что делает их более универсальными.
  • Сложные типы: Intersection Types позволяют создавать сложные типы, которые объединяют свойства нескольких других типов, что полезно для работы с объектами, которые должны соответствовать нескольким интерфейсам.
  • Повышенная безопасность типов: Использование Union и Intersection Types помогает избежать ошибок типов, обеспечивая более строгую проверку на этапе компиляции.

7.3 Примеры комбинирования Union и Intersection Types

TypeScript позволяет комбинировать Union и Intersection Types для создания еще более сложных типовых структур.

Пример:

JavaScript
    
      "use strict";
      function getVehicle(vehicle) {
          if (vehicle === 'car-plane') {
              return {
                  drive() {
                      console.log('Driving');
                  },
                  fly() {
                      console.log('Flying');
                  }
              };
          }
          else {
              return null;
          }
      }
      let carPlane = getVehicle('car-plane');
      carPlane === null || carPlane === void 0 ? void 0 : carPlane.drive(); // Вывод: Driving
      carPlane === null || carPlane === void 0 ? void 0 : carPlane.fly(); // Вывод: Flying
    
  
TypeScript
    
      interface Drivable {
        drive(): void;
      }

      interface Flyable {
        fly(): void;
      }

      type Vehicle = Drivable & Flyable;
      type VehicleType = 'car' | 'plane' | 'car-plane';

      function getVehicle(vehicle: VehicleType): Vehicle | null {
        if (vehicle === 'car-plane') {
          return {
            drive() {
              console.log('Driving');
            },
            fly() {
              console.log('Flying');
            }
          };
        } else {
          return null;
        }
      }

      let carPlane = getVehicle('car-plane');
      carPlane?.drive(); // Вывод: Driving
      carPlane?.fly(); // Вывод: Flying
    
  

В этом примере Vehicle является пересечением типов Drivable и Flyable, а VehicleType является Union Type, представляющим возможные типы транспортных средств. Функция getVehicle возвращает объект, который может как ездить, так и летать, или null, если тип транспортного средства не совпадает.

Примеры использования Union и Intersection Types в реальных проектах

Union и Intersection Types часто используются в реальных проектах для обработки данных из различных источников, создания многофункциональных объектов и обеспечения гибкости при работе с API.

Пример:

JavaScript
    
      "use strict";
      function handleResponse(response) {
          if (response.status === 200) {
              console.log('Data:', response.data);
          }
          else {
              console.error('Error:', response.error);
          }
      }
      let successResponse = { status: 200, data: { id: 1, name: 'Test' } };
      let errorResponse = { status: 404, error: 'Not Found' };
      handleResponse(successResponse); // Вывод: Data: { id: 1, name: 'Test' }
      handleResponse(errorResponse); // Вывод: Error: Not Found
    
  
TypeScript
    
      type ApiResponse = { status: 200, data: any } | { status: number, error: string };

      function handleResponse(response: ApiResponse): void {
        if (response.status === 200) {
          console.log('Data:', response.data);
        } else {
          console.error('Error:', response.error);
        }
      }

      let successResponse: ApiResponse = { status: 200, data: { id: 1, name: 'Test' } };
      let errorResponse: ApiResponse = { status: 404, error: 'Not Found' };

      handleResponse(successResponse); // Вывод: Data: { id: 1, name: 'Test' }
      handleResponse(errorResponse); // Вывод: Error: Not Found
    
  

В этом примере интерфейс ApiResponse использует Union Types для описания возможных структур ответа API. Функция handleResponse обрабатывает успешные и ошибочные ответы.

3
Задача
Модуль 2: Fullstack, 4 уровень, 6 лекция
Недоступна
Параметр типа string | number
Параметр типа string | number
3
Задача
Модуль 2: Fullstack, 4 уровень, 6 лекция
Недоступна
Применение Intersection Types
Применение Intersection Types
3
Задача
Модуль 2: Fullstack, 4 уровень, 6 лекция
Недоступна
Комбинирование Union и Intersection Types
Комбинирование Union и Intersection Types
3
Задача
Модуль 2: Fullstack, 4 уровень, 6 лекция
Недоступна
Обработка ответа API с Union Types
Обработка ответа API с Union Types
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ