Коротко: Пошаговое руководство по генерации типобезопасного API-клиента и React-хуков в RTK Query из OpenAPI/Swagger с помощью @rtk-query/codegen-openapi.
Ручной перенос DTO-интерфейсов и декларация эндпоинтов в RTK Query неизбежно приводят к рассинхронизации контрактов между клиентом и сервером. Любое изменение поля на бэкенде, не замеченное во фронтенд-коде, превращается в скрытый баг в рантайме. Автоматическая генерация API-слоя на базе спецификации OpenAPI (Swagger) решает эту проблему: типы данных, методы запросов и React-хуки формируются напрямую из схемы.
Официальная утилита @rtk-query/codegen-openapi, входящая в экосистему Redux Toolkit, позволяет полностью исключить рутинное написание бойлерплейта и гарантирует строгую типобезопасность на этапе компиляции TypeScript.
Архитектура кодогенерации в RTK Query
Инструмент @rtk-query/codegen-openapi анализирует JSON- или YAML-схему OpenAPI (v2 или v3) и преобразует ее в полноценный API-слайс для RTK Query.
Концепция Base API и Code Splitting
Архитектура строится на механизме разделения эндпоинтов (injectEndpoints). Вместо создания монолитного клиента с нуля рабочий процесс разделяется на две части:
- Базовый API (
emptySplitApi) — вручную созданный модуль, в котором настраиваются базовый URL, заголовки авторизации, обработка повторных попыток (retry) и кастомныйbaseQuery. - Сгенерированный API — автоматически создаваемый файл, который импортирует базовый API и внедряет в него эндпоинты через вызов
.injectEndpoints().
Такой подход позволяет изолировать сгенерированный код от кастомной логики приложения, а также дробить API на несколько независимых чанков при масштабировании кодовой базы.
┌────────────────────────┐
│ OpenAPI / Swagger │
│ Спецификация │
└───────────┬────────────┘
│ @rtk-query/codegen-openapi
▼
┌────────────────────────┐ ┌────────────────────────┐
│ Сгенерированный │ ───▶ │ Базовый API │
│ API-файл (Endpoints, │ inject│ (BaseQuery, Auth, │
│ Types, Hooks) │ │ Custom Headers) │
└────────────────────────┘ └────────────────────────┘
Что входит в сгенерированный артефакт
В выходном файле кодогенератор формирует:
- TypeScript-типы: интерфейсы для тел запросов (Request Body), параметров строки запроса (Query Params), параметров пути (Path Params) и моделей ответов (Responses).
- Эндпоинты RTK Query: вызовы
builder.queryиbuilder.mutationсо строго привязанными типами аргументов и ответов. - React-хуки: готовые хуки вида
useGetUsersQuery,useUpdateUserMutationиuseLazyGetUsersQuery.
Пошаговая настройка @rtk-query/codegen-openapi
Шаг 1. Установка зависимостей
Для работы кодогенератора установите пакет в качестве dev-зависимости:
npm install -D @rtk-query/codegen-openapi
Убедитесь, что в проекте уже установлены базовые библиотеки @reduxjs/toolkit и react-redux.
Шаг 2. Создание базового API-слайса
Создайте файл src/shared/api/emptyApi.ts. В нем объявляется базовый инстанс с конфигурацией сети:
// src/shared/api/emptyApi.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const emptySplitApi = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'https://api.example.com/v1',
prepareHeaders: (headers) => {
const token = localStorage.getItem('access_token');
if (token) {
headers.set('authorization', `Bearer ${token}`);
}
return headers;
},
}),
endpoints: () => ({}),
});
Шаг 3. Конфигурационный файл (openapi-config.ts)
В корне проекта или в директории конфигураций создайте файл настроек генератора. Пакет предоставляет интерфейс ConfigFile для проверки параметров:
// openapi-config.ts
import type { ConfigFile } from '@rtk-query/codegen-openapi';
const config: ConfigFile = {
schemaFile: 'https://api.example.com/v1/openapi.json', // или локальный путь: './schema.json'
apiFile: './src/shared/api/emptyApi.ts',
apiImport: 'emptySplitApi',
outputFile: './src/shared/api/generatedApi.ts',
exportName: 'generatedApi',
hooks: true,
};
export default config;
Основные параметры конфигурации:
schemaFile— URL или относительный путь к файлу схемы (JSON или YAML).apiFile— путь к файлу с базовым API-клиентом.apiImport— имя экспортируемой переменной базового API.outputFile— путь к файлу, в который будет записан результат генерации.exportName— имя экспортируемого расширенного API.hooks— при значенииtrueгенерирует React-хуки для каждого эндпоинта.
Шаг 4. Настройка npm-скрипта и запуск генерации
Добавьте команду запуска в секцию scripts файла package.json:
{
"scripts": {
"codegen:api": "rtk-query-codegen-openapi openapi-config.ts"
}
}
Запустите команду в терминале:
npm run codegen:api
После завершения процесса в файле src/shared/api/generatedApi.ts появятся типизированные методы и хуки, готовые к использованию в React-компонентах:
// Пример использования в компоненте
import { useGetUserByIdQuery, useUpdateUserMutation } from '@/shared/api/generatedApi';
export const UserProfile = ({ userId }: { userId: string }) => {
const { data: user, isLoading, isError } = useGetUserByIdQuery({ id: userId });
const [updateUser] = useUpdateUserMutation();
if (isLoading) return <div>Загрузка...</div>;
if (isError || !user) return <div>Ошибка загрузки</div>;
return (
<div>
<h1>{user.name}</h1>
<button onClick={() => updateUser({ id: userId, userDto: { name: 'Новое имя' } })}>
Обновить
</button>
</div>
);
};
Тонкая настройка: энумы, валидация и расширение эндпоинтов
Управление стилем перечислений (enumStyle)
По умолчанию генератор может компилировать OpenAPI enum в классические конструкции enum TypeScript. Если в проекте принят стандарт использования строковых литеральных типов или объектов as const, поведение генератора корректируется опцией enumStyle:
// openapi-config.ts
const config: ConfigFile = {
// ...
enumStyle: 'as-const', // варианты: 'enum' | 'as-const' | 'union'
};
'union'формирует объединение типов:type Status = 'active' | 'inactive';'as-const'формирует объект-константу и выводит тип:export const Status = { Active: 'active', ... } as const;
Генерация регулярных выражений для валидации
Если в OpenAPI-схеме для строковых полей заданы свойства pattern, кодогенератор извлекает их в виде скомпилированных регулярных выражений:
export const userEmailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
Эти паттерны можно переиспользовать в схемах валидации форм (Zod, Yup) на стороне фронтенда, сохраняя полную синхронизацию с серверными правилами.
Инвалидация кэша через enhanceEndpoints
Сгенерированный файл нельзя редактировать вручную — любые изменения перезаписываются при повторном запуске генератора. Для настройки тегов кэширования (providesTags, invalidatesTags) используется метод enhanceEndpoints:
// src/shared/api/apiWithTags.ts
import { generatedApi } from './generatedApi';
export const enhancedApi = generatedApi.enhanceEndpoints({
addTagTypes: ['User', 'Post'],
endpoints: {
getUserById: {
providesTags: (result, error, arg) => [{ type: 'User', id: arg.id }],
},
updateUser: {
invalidatesTags: (result, error, arg) => [{ type: 'User', id: arg.id }],
},
},
});
export const { useGetUserByIdQuery, useUpdateUserMutation } = enhancedApi;
Интеграция в рабочий процесс и CI/CD
Автоматизация генерации API-клиента требует выстроенных процессов в команде:
- Коммит сгенерированных файлов в репозиторий: сгенерированные файлы рекомендуется фиксировать в Git. Это обеспечивает быстрый старт проекта без предварительной сборки, гарантирует работу автокомплита в IDE сразу после клонирования репозитория и позволяет отслеживать изменения контрактов на этапе Code Review.
- Проверка актуальности в CI: в пайплайн сборки добавляется шаг, запускающий кодогенерацию и проверяющий статус рабочей директории. Если схема на бэкенде изменилась, а разработчик не обновил клиент, команда
git diff --exit-codeзавершит сборку с ошибкой:
# Пример шага в GitHub Actions
- name: Check API Types Drift
run: |
npm run codegen:api
git diff --exit-code src/shared/api/generatedApi.ts
Частые ошибки и ограничения кодогенерации
- Неконсистентный или отсутствующий
operationId: кодогенератор опирается на полеoperationIdв схеме для формирования имен методов и хуков. Если бэкенд не указываетoperationId, имена эндпоинтов строятся на основе HTTP-метода и пути (например,getApiV1UsersById), что усложняет чтение кода. - Мутации с ответом
204 No Content: если бэкенд возвращает пустой ответ, но в схеме не указан тип возвращаемого значенияvoidили пустой Response Object, TypeScript может типизировать ответ какunknown. - Прямое редактирование выходного файла: любые ручные изменения типов или параметров в сгенерированном файле теряются при повторной генерации. Вся кастомизация должна производиться через
enhanceEndpointsили внешние утилитарные типы TypeScript.
Часто задаваемые вопросы (FAQ)
Можно ли генерировать несколько API-клиентов для разных микросервисов?
Да. Для этого создается массив конфигураций или отдельные конфигурационные файлы для каждого сервиса. Все они могут внедрять эндпоинты в единый emptySplitApi или использовать изолированные базовые слайсы для разных доменов.
Что делать, если на бэкенде нет валидных operationId?
Генератор сформирует имена функций автоматически по структуре пути и HTTP-глаголу. Однако предпочтительнее договориться с бэкенд-командой о корректной генерации operationId через Swagger-декораторы контроллеров.
Поддерживаются ли схемы OpenAPI в формате YAML?
Да, параметр schemaFile принимает прямые ссылки и пути как к .json, так и к .yaml / .yml файлам.
Как переопределить тип ответа, если схема бэкенда неточна?
Используйте enhanceEndpoints и метод transformResponse для преобразования данных либо уточняйте типы с помощью TypeScript-утилит (Omit, Pick, объединения типов) на уровне компонентов.
Как передавать динамические заголовки?
Динамические параметры запросов настраиваются один раз в emptySplitApi внутри prepareHeaders или через кастомную обертку над baseQuery. Сгенерированные эндпоинты автоматически наследуют эту конфигурацию.
Заключение
Использование @rtk-query/codegen-openapi переводит интеграцию фронтенда с API на уровень строгого контрактного программирования. Кодогенерация избавляет команду от ручного описания DTO-типов, снижает объем технического долга и предотвращает рассинхронизацию интерфейсов при непрерывной поставке изменений. Описанный подход позволяет безопасно масштабировать кодовую базу и сосредоточиться на реализации бизнес-логики приложения.




.svg.webp)




