Бітрікс-проєкт із каталогом на 50 000 товарів — це постійна боротьба з невідповідністю типів. Під час передачі даних з PHP у JavaScript часто випливають баги: undefined is not an object, неправильні типи цін, злетілі фільтри. Ми регулярно стикалися з цим на проєктах будь-якої складності. TypeScript закриває цю проблему: статична типізація ловить помилки на етапі компіляції, а не в браузері користувача. Досвід нашої команди — 8 років у Бітрікс та понад 50 реалізованих проєктів з TypeScript-архітектурою. Результат: зниження вартості багфіксу на 30–50% і скорочення часу на налагодження інтеграцій. На одному проєкті економія на багфіксах склала суттєву суму за перший рік після міграції.
Чому TypeScript, а не ванільний JavaScript для Бітрікс?
Згідно з TypeScript Handbook (на Wikipedia), статична типізація запобігає до 15% помилок на етапі компіляції. У контексті Бітрікс це критично: невірний тип ціни або ID товару може призвести до падіння кошика. На одному з проєктів із каталогом на 100 000 товарів ми повністю усунули баги фільтрації після переходу на строгу типізацію. TypeScript-фронтенд у 2–3 рази надійніший за аналогічне рішення на чистому JS: помилки типів, некоректна передача даних між PHP та JS, проблеми з кешуванням — все це виявляється до викладки в продакшн.
Як відбувається інтеграція TypeScript із PHP-компонентами?
Ми використовуємо покроковий підхід, щоб мінімізувати простої:
- Аудит поточного JS-коду: виявляємо невідповідності типів, глобальні змінні, слабкі місця.
- Проєктування типів для всіх точок інтеграції з PHP (інфоблоки, REST, компоненти).
- Налаштування збірника Vite або Webpack з підтримкою TypeScript.
- Розробка компонентів з повною типізацією — каталог, кошик, фільтр.
- Тестування та деплой з гарантією стабільності.
Архітектура TypeScript у шаблоні Бітрікс
Два основні підходи, які ми застосовуємо:
| Підхід | Опис | Коли вибирати |
|---|---|---|
| MPA з TypeScript-модулями | Класична генерація сторінок на PHP, JavaScript — острівці інтерактивності. Кожен компонент — ізольований модуль із власними типами. | Проєкти середнього розміру, де SEO та швидкість першого завантаження критичні. |
| SPA/Headless | React або Vue на TypeScript повністю керують UI, Бітрікс виступає як API (REST/GraphQL). | Складні користувацькі інтерфейси: кабінет клієнта, CRM-віджети, багатокрокові форми. |
Більшість наших проєктів використовують перший підхід з елементами другого в найбільш інтерактивних частинах (каталог, кошик, особистий кабінет).
Приклад структури компонентів
/local/templates/my_site/
├── src/
│ ├── components/
│ │ ├── catalog/
│ │ │ ├── CatalogFilter.ts
│ │ │ ├── ProductCard.ts
│ │ │ └── CartButton.ts
│ │ ├── cart/
│ │ │ ├── CartDrawer.ts
│ │ │ └── CartCounter.ts
│ │ └── common/
│ │ ├── Modal.ts
│ │ └── Tooltip.ts
│ ├── api/
│ │ ├── catalog.ts
│ │ ├── cart.ts
│ │ └── user.ts
│ ├── types/
│ │ ├── bitrix.d.ts
│ │ └── api.ts
│ ├── utils/
│ │ ├── http.ts
│ │ └── format.ts
│ └── main.ts
├── dist/
├── package.json
├── tsconfig.json
└── vite.config.ts
Компонент кошика на TypeScript
Приклад типізованого компонента додавання в кошик:
// api/cart.ts
interface CartItem {
id: number;
name: string;
price: number;
quantity: number;
img: string | null;
}
interface CartState {
items: CartItem[];
totalPrice: number;
totalCount: number;
currency: string;
}
interface AddToCartPayload {
productId: number;
quantity: number;
properties?: Record<string, string>;
}
export async function addToCart(payload: AddToCartPayload): Promise<CartState> {
const formData = new FormData();
formData.append('sessid', BX.bitrix_sessid());
formData.append('action', 'addItem');
formData.append('product_id', String(payload.productId));
formData.append('quantity', String(payload.quantity));
if (payload.properties) {
Object.entries(payload.properties).forEach(([k, v]) => {
formData.append(`props[${k}]`, v);
});
}
const res = await fetch('/local/ajax/cart.php', {
method: 'POST',
body: formData,
});
if (!res.ok) throw new Error(`Cart error: ${res.status}`);
const json = await res.json();
if (json.status !== 'success') throw new Error(json.error ?? 'Cart error');
return json.cart as CartState;
}
Інтеграція з PHP-компонентами через data-атрибути
Передача даних із шаблону в TypeScript без глобальних змінних:
// template.php компонента каталогу
<div
id="catalog-app"
data-section-id="<?= (int)$arResult['SECTION']['ID'] ?>"
data-iblock-id="<?= (int)$arParams['IBLOCK_ID'] ?>"
data-initial-filter='<?= htmlspecialchars(
json_encode($arResult['FILTER_PARAMS']), ENT_QUOTES
) ?>'
>
<?php // SSR-верстка для першого завантаження ?>
</div>
// TypeScript читає дані типізовано
const appEl = document.getElementById('catalog-app');
if (!appEl) throw new Error('#catalog-app not found');
const sectionId = Number(appEl.dataset['sectionId']);
const iblockId = Number(appEl.dataset['iblockId']);
const rawFilter = appEl.dataset['initialFilter'] ?? '{}';
const initFilter = JSON.parse(rawFilter) as FilterState;
Як Vite пришвидшує збірку TypeScript-фронтенду?
Для багатомодульних проєктів використовуємо Vite — він дає швидку збірку та розділення точок входу.
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
root: 'src',
build: {
outDir: '../dist',
emptyOutDir: true,
rollupOptions: {
input: {
main: 'src/main.ts',
catalog: 'src/pages/catalog.ts',
cart: 'src/pages/cart.ts',
},
},
},
resolve: {
alias: { '@': '/src' },
},
});
Окремі entrypoint для кожного розділу сайту — лише потрібний JavaScript завантажується на сторінці, що покращує швидкість завантаження.
Реальний кейс: каталог на 100 000 товарів
Наш клієнт — інтернет-магазин з каталогом на 100 000 позицій. Продукт: динамічні фільтри, кошик з безліччю опцій, інтеграція з 1С через CommerceML. Вихідний код на ванільному JS страждав від помилок типів при обміні з 1С. Ми провели аудит, спроєктували типи для всіх сутностей і мігрували фронтенд на TypeScript за три тижні. Результат: кількість помилок у кошику знизилася на 60%, час завантаження фільтрів — на 30%. Клієнт отримав гарантію стабільності на наступні два роки, а економія на багфіксах склала значну суму за перший рік.
Що входить у нашу роботу з розробки TypeScript-фронтенду
- Аудит поточної архітектури: виявлення проблем у JS-коді, оцінка обсягу міграції.
- Налаштування TypeScript + збірник (Vite/Webpack) з урахуванням оточення Бітрікс.
- Створення типів для всіх точок інтеграції з PHP (інфоблоки, REST, компоненти).
- Розробка нових компонентів (каталог, кошик, фільтр, особистий кабінет) з повною типізацією.
- Міграція існуючого коду з ванільного JS на TypeScript зі збереженням функціональності.
- Документація з архітектури та опис типів.
- Тестування та налагодження в продакшні з гарантією стабільності.
Орієнтовні терміни
| Етап | Терміни |
|---|---|
| Аудит та проєктування архітектури | 1–2 дні |
| Налаштування інфраструктури TypeScript + Vite | 1 день |
| Розробка компонентів каталогу (фільтр, список, картка) | 3–5 днів |
| Розробка кошика та міні-кошика в шапці | 2–3 дні |
| Міграція існуючого JS-коду (залежить від обсягу) | 2–5 днів |
| Тестування та деплой | 1–2 дні |
Точні терміни та вартість розраховуються індивідуально після знайомства з проєктом. Замовте аудит вашого проєкту — ми проаналізуємо ваш код і запропонуємо оптимальне рішення. Отримайте консультацію, щоб зрозуміти, як TypeScript скоротить ваші витрати на підтримку фронтенду.







