Назад в блог

Bitrix REST API и TypeScript: контракт, который мы сгенерировали сами

Когда мы переводили каталог на 28 000 позиций в headless-архитектуру, первые две недели прошли в одном режиме. Открываешь метод Bitrix REST, смотришь на документацию — документация отстаёт от текущей версии месяца на три. Открываешь дебаггер, вызываешь метод, смотришь на реальный ответ. Делаешь вывод о форме. Пишешь интерфейс вручную. На следующий день коллега делает то же самое с другим методом — чуть иначе, чуть другие предположения.

Через месяц у нас было 40+ any в TypeScript и два инцидента в проде: один с ценой, один с остатком.

Почему Bitrix REST без схемы — это не просто неудобство

Bitrix REST API — де-факто стандарт для headless-интеграций на Bitrix. Но у него нет OpenAPI-спецификации, нет JSON Schema, нет официального клиента с типами. Это API эпохи PHP-монолита, где форма ответа определяется только в исходниках модуля или в документации, которую не всегда успевают обновить.

Когда мы разбирали неочевидные стороны Bitrix REST API, говорили про лимиты и паджинацию. Типизация — отдельная история. Для Next.js-разработчика выбор такой: либо any везде, либо типизация вручную. Первое — хрупкость. Второе — работа, которая протухает при каждом обновлении Bitrix.

Мы нашли третий путь.

Три способа типизировать Bitrix REST

Три варианта.

Первый — ручные интерфейсы. Пишем TypeScript-типы по документации и дебаггеру. Быстро в начале, но типы устаревают незаметно. Bitrix обновился, форма ответа изменилась, тип неверный — ошибка в проде при следующей деплойке фронта.

Второй — Zod inference. Описываем схему через Zod, TypeScript-тип выводится автоматически. Работает, но писать Zod-схемы для каждого метода вручную — тот же объём работы, что и ручные интерфейсы. Плюс ещё рантайм-валидация, которую мы не просили.

Третий — генерация из реальных ответов. Вызываем каждый нужный метод с реальными данными, сохраняем ответ, генерируем TypeScript-тип. Тип отражает реальность, а не документацию.

Мы выбрали третий.

Наш подход: ts-morph и 600 строк контракта

Технически это скрипт на ts-morph. Он делает три вещи.

Вызывает каждый нужный Bitrix REST-метод через HTTP с реальными параметрами. Для 28k SKU каталога это были catalog.product.list, catalog.product.offer.list, sale.order.add, crm.lead.add и ещё восемь методов.

Сохраняет ответ как JSON-артефакт в репозитории. Это источник правды — файл коммитится.

Генерирует TypeScript-интерфейс из формы JSON. На выходе получается bitrix-api.types.ts — на момент первого запуска 600 строк.

Скрипт запускается в CI перед каждым деплоем фронта. Если форма ответа изменилась — тип-чек ловит это до production.

Первый реальный случай

Через три месяца после запуска Bitrix обновился. В ответе catalog.product.list появилось новое поле PREVIEW_PICTURE_VARIANTS — массив с несколькими размерами изображения вместо одного PREVIEW_PICTURE.

Без типизации это обнаружилось бы как сломанные изображения в карточках товаров — в проде, при следующем деплое фронта. С типизацией — как ошибка в CI за 4 минуты до деплоя.

Разница: 15 минут на фикс в CI против потенциального инцидента с роллбэком.

Что изменилось на code review

Когда разработчик делает PR с изменением интеграции, в diff появляется файл bitrix-api.types.ts. Видно, какое поле добавилось, что изменило тип, что удалилось.

Раньше такие изменения жили только в голове — «я думаю, тут string | null». Теперь это явная строка в коде, которую ревьюер видит и может оспорить.

Небольшой сдвиг. Типы перестали быть предположениями — стали частью контракта.

Почему OpenAPI-генераторы не подошли

Мы пробовали community-решения, которые парсят Bitrix REST-документацию и генерируют OpenAPI-схему. Результат: схема неточная, половина методов покрыта частично, any там же, где у нас.

Проблема системная. Документация Bitrix — не спецификация. Реальный ответ часто отличается: дополнительные поля, другие null/undefined паттерны, вариативные типы при разных флагах запроса. Только реальный ответ с реальными данными даёт правильный тип.

Что измерили

За шесть месяцев после внедрения — 0 runtime-ошибок, связанных с формой Bitrix REST-ответа. До внедрения — около двух инцидентов в месяц, которые доходили до клиента или до staging в момент выкатки.

Дополнительный эффект: онбординг нового разработчика ускорился. Файл bitrix-api.types.ts — документация по всем используемым методам. Не нужно читать Bitrix-docs, чтобы понять, что возвращает метод.

Что не стали делать

Мы не покрываем всё Bitrix REST API — это несколько сотен методов. Только те, которые реально используются в проекте. При добавлении нового метода — добавляем вызов в генератор, прогоняем, получаем тип.

Также нет автоматического обновления типов по расписанию. Обновление — только при явном изменении интеграции. Иначе шум, который никто не читает.

Итог

Bitrix REST API хорошо работает для headless-архитектуры, но требует дисциплины на стороне фронта. Генерация TypeScript-типов из реальных ответов — это архитектурная дисциплина, а не опциональная надстройка. Контракт между PHP-бэком и Next.js-фронтом должен быть явным.

3-4 часа на генератор. Окупается на первом обновлении Bitrix.

Про то, как выстроить весь headless-пайплайн до запуска — три вещи, которые я проверяю до любого headless-проекта.