Как Orval спасает от рутины при работе с API на TypeScript
Представьте, что бэкенд-разработчик прислал вам обновленный Swagger на 50 эндпоинтов. Вы открываете проект и понимаете: следующие пару часов уйдут на то, чтобы вручную переписать интерфейсы, обновить zod-схемы и проверить, не изменились ли параметры в хуках react-query. Это скучно, это чревато опечатками, и, честно говоря, это работа, которую должен делать компьютер, а не человек.
Именно эту проблему решает orval. Он берет ваш файл спецификации OpenAPI (v3 или Swagger v2) и превращает его в полностью типизированный клиент.
Что это за зверь
Если коротко, orval — это генератор кода. Но в отличие от громоздкого openapi-generator, который часто тянет за собой странные зависимости и выдает не самый читаемый код, этот инструмент сфокусирован на современной TypeScript-экосистеме.
Я часто вижу, как в проектах пытаются писать API-слой руками. Сначала это кажется нормальным, но когда проект разрастается до сотни эндпоинтов, поддерживать актуальность типов становится невозможно. Orval просто автоматизирует этот процесс, подстраиваясь под ваш стек: от React и Vue до Angular и даже Hono.
Чем он хорош на практике
Главная фишка проекта — гибкость. Он не навязывает вам конкретную библиотеку для запросов.
Умная генерация хуков
Вместо того чтобы просто дать вам fetch с типами, orval может сгенерировать готовые хуки для TanStack Query (бывший React Query), SWR или Vue Query. Это значит, что вы получаете не просто функцию getData(), а типизированный useGetDataQuery(), в котором уже прописаны все ключи кеширования и типы ответа.
Интеграция с Zod и MSW
Это, пожалуй, мои любимые функции. Orval умеет генерировать схемы валидации для zod на основе той же спецификации. Если бэкенд говорит, что поле email обязательное и должно быть строкой, у вас появится готовая схема для проверки данных на клиенте.
А еще он умеет создавать моки для MSW (Mock Service Worker). Это спасает, когда фронтенд нужно делать быстрее бэкенда. Вы запускаете генерацию, и у вас есть рабочий мок-сервер, который отдает данные нужной структуры.
Архитектурная чистота
Инструмент разделяет модели (типы данных) и сами запросы. Вы можете сгенерировать только интерфейсы TypeScript, если вам не нужны готовые функции вызова API. Это удобно, если у вас уже есть своя обертка над axios или fetch.
Как это работает под капотом
Внутри проекта используется Bun для сборки и управления пакетами, что намекает на акцент на скорость. Конфигурация обычно описывается в файле orval.config.js. Там вы указываете путь к Swagger-файлу и выбираете, какой клиент хотите получить на выходе.
Пример простой настройки выглядит примерно так:
module.exports = {
'petstore-file': {
input: './petstore.yaml',
output: {
target: './src/api/endpoints/petstore.ts',
schemas: './src/api/model',
client: 'react-query',
mock: true,
},
},
};
После запуска одной команды вы получаете готовый слой API, который остается только импортировать в компоненты.
Кому стоит попробовать
Я бы советовал внедрять orval в следующих случаях:
- Вы используете TypeScript и ваш бэкенд честно описывает API в Swagger/OpenAPI.
- Проект живет в режиме активной разработки, и контракты API часто меняются.
- Вы используете
TanStack Queryи устали каждый раз писать обертки для типов вручную.
Если у вас маленький пет-проект на три запроса, возможно, это будет лишним усложнением. Но для любого мало-мальски серьезного продукта автоматизация типизации окупается в первую же неделю.
На что обратить внимание
Недавно вышла версия 8.0.0, в которой много изменений. Если решите попробовать на старом проекте, обязательно загляните в Migration Guide на официальном сайте orval.dev.
Кстати, у разработчиков есть классный Playground, где можно вставить свой YAML и сразу увидеть, какой код получится на выходе. Это отличный способ проверить, подходит ли вам стиль генерируемого кода, прежде чем тащить библиотеку в проект.
Orval — это не «волшебная палочка», но это очень надежный «рабочий мул». Он делает ровно то, что обещает: избавляет от копипасты типов и гарантирует, что ваш фронтенд не упадет из-за того, что кто-то переименовал поле в базе данных, а вы забыли это поправить в коде.
Попробовать стоит хотя бы ради генерации моков MSW — это экономит уйму нервов при разработке фич в изоляции.
