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-проекта.