Весной стартует сезон найма, успей отхватить свой оффер!

Utility Type Extract в TypeScript

Extract — это utility тип в TypeScript, который извлекает из union-типа те члены, которые можно присвоить другому указанному типу. По сути, он создаёт новое объединение, оставляя только «пересекающиеся» части.


Синтаксис

Extract<T, U>
  • T — исходный union-тип (объединение).
  • U — тип (или union), члены которого нужно оставить из T.

Extract<T, U> сохраняет в T только те типы, которые можно присвоить U, убирая всё остальное.


Когда использовать Extract

  1. Извлечение допустимых значений: например, если API может возвращать "success" | "error" | "pending", можно вычленить только "error".
  2. Фильтрация по ролям и доступам: из списка всех ролей можно извлекать только администраторов (Extract<Role, "admin" | "moderator">).
  3. Оптимизация union-типов: когда нужно оставить только значения определённого типа.
  4. Упрощение работы с дженериками: если в шаблон передаётся большой список вариантов, Extract поможет сузить его до нужных значений.

Примеры

Пример 1. Извлечение чисел и булевых значений

type Mixed = string | number | boolean;

// Извлекаем только числа и булевы значения
type OnlyNumbersOrBooleans = Extract<Mixed, number | boolean>;
// OnlyNumbersOrBooleans = number | boolean
  • В исходном типе Mixed есть string, number, и boolean.
  • Extract оставляет лишь те типы, которые являются number или boolean.

Пример 2. Пример с API: Фильтрация ошибок

type ApiResponse = 
  | { status: "success"; data: string } 
  | { status: "error"; message: string }
  | null
  | undefined;

// Извлекаем только ошибки
type ErrorResponse = Extract<ApiResponse, { status: "error" }>;

function handleError(response: ApiResponse) {
  if (response && response.status === "error") {
    console.log("Ошибка:", response.message);
  }
}

// Использование:
const res1: ApiResponse = { status: "success", data: "OK" };
const res2: ApiResponse = { status: "error", message: "Ошибка запроса" };

handleError(res1); // Ничего не выводит
handleError(res2); // Выведет: "Ошибка: Ошибка запроса"

Что здесь происходит?

  1. Extract<ApiResponse, { status: "error" }> оставляет только те объекты, у которых status: "error".
  2. Мы используем это для обработки ошибок, игнорируя успешные ответы и null | undefined.
  3. Функция handleError проверяет, является ли ответ ошибочным, и выводит сообщение.

Это более реальный кейс, так как обработка API-ответов — частая задача во фронтенд-разработке. 🚀


Отличие от Exclude

УтилитаОписание
Exclude<T, U>Исключает все подтипы из T, которые совместимы с U
Extract<T, U>Оставляет только подтипы из T, которые совместимы с U

Пример:

type Mixed = string | number | boolean;

type OnlyStrings = Exclude<Mixed, number | boolean>; 
// string

type OnlyNumbersOrBooleans = Extract<Mixed, number | boolean>;
// number | boolean

Итог

  • Extract позволяет вычленить нужные подтипы из объединения, сохраняя только те, которые соответствуют заданному типу.
  • Упрощает логику работы с типами, особенно когда требуется «точечно» отсеять часть вариантов, оставив желаемые.
  • Часто идёт в паре с Exclude, решая прямо противоположную задачу (исключение vs. извлечение).