TypeScript for 1C-Bitrix: Typed Development

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Showing 1 of 1All 1626 services
TypeScript for 1C-Bitrix: Typed Development
Medium
~1-2 weeks
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1356
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    943
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    693
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    828
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    731
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    1073

PHP Bitrix templates generate HTML, and frontend code in plain JavaScript remains without types: no autocompletion, no early error detection. As long as the JS code is small, it's tolerable. When it exceeds 500 lines, problems begin: undefined is not a function in production, context loss, data structure mismatches. TypeScript is the pragmatic choice we apply to all projects. Our team of certified Bitrix developers has accumulated experience in implementing TypeScript in dozens of projects. Result: bug count is reduced by 40–60%, and refactoring speed doubles.

TypeScript is a programming language that extends JavaScript with static typing (Wikipedia).

Why TypeScript is a Must-Have for Bitrix?

Bitrix is not just a CMS but a platform with thousands of integration points: 1C, payment gateways, CRM. Each integration adds its own JS layer. Without types, it's easy to confuse fields ID (string) with IBLOCK_ID (number), forget sessid, or get Uncaught TypeError. TypeScript catches these errors at compile time, not in the user's browser.

Comparison: a JS project with 2000 lines statistically contains 15–25 implicit errors. A TypeScript equivalent — 3–5. The difference is 5 times. Development speed with TypeScript increases by 1.5–2 times due to autocompletion and early error detection.

Where TypeScript Lives in a Bitrix Project?

Two typical scenarios: TypeScript in a site template and TypeScript in a D7 module.

In the site template:

/local/templates/my_site/
    src/
        ts/
            catalog.ts
            cart.ts
            search.ts
        scss/
            ...
    dist/        <- compiled JS
    package.json
    tsconfig.json
    vite.config.ts

In the module:

/local/modules/mymodule/
    install/
        js/
            src/         <- TypeScript sources
                index.ts
            dist/        <- compiled JS
    package.json
    tsconfig.json

tsconfig.json for Bitrix Environment

{
    "compilerOptions": {
        "target": "ES2020",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "strict": true,
        "noUncheckedIndexedAccess": true,
        "lib": ["ES2020", "DOM"],
        "outDir": "./dist",
        "sourceMap": true,
        "paths": {
            "@/*": ["./src/*"]
        }
    },
    "include": ["src/**/*.ts"],
    "exclude": ["node_modules", "dist"]
}

noUncheckedIndexedAccess: true — strict check for array indexing. Critical for working with API results where a field may be missing.

More about Vite configuration for Bitrix

Vite is a modern bundler that is significantly faster than Webpack. For Bitrix, minimal configuration is enough: specify the entry point and output folder. Vite automatically supports TypeScript, CSS preprocessors, and hot-reload during development. Example vite.config.ts:

import { defineConfig } from 'vite';

export default defineConfig({
    build: {
        outDir: './dist',
        rollupOptions: {
            input: './src/ts/index.ts',
        },
    },
});

In production build, we get minified JS that is included in the template.

How to Type Data from Bitrix?

Project: an online store with a catalog of 50,000 products. Integration with 1C via CommerceML. Data comes from the PHP backend via AJAX. Previously, plain JS was used — any change in structure broke the frontend. We implemented TypeScript and described types for all entities.

Types for the Catalog

// types/bitrix.ts
export interface BitrixProduct {
    ID: string;
    NAME: string;
    DETAIL_PAGE_URL: string;
    PREVIEW_PICTURE: string | null;
    CATALOG_PRICE_1: string | null;
    CATALOG_CURRENCY_1: string;
    PROPERTY_BRAND_VALUE: string | null;
    PROPERTY_ARTICLE_VALUE: string | null;
}

export interface BitrixCatalogResult {
    ITEMS: BitrixProduct[];
    TOTAL_ITEMS_COUNT: number;
    PAGES_COUNT: number;
    CURRENT_PAGE: number;
}

export interface BitrixAjaxResponse<T = unknown> {
    status: 'success' | 'error';
    data: T;
    errors?: BitrixError[];
}

export interface BitrixError {
    code: string;
    message: string;
    customData?: string;
}

Important: Bitrix returns numeric IDs as strings — ID: "42". This is reflected in the type. Also, all optional fields are explicitly marked | null.

Typed AJAX Function

// api/catalog.ts
import type { BitrixAjaxResponse, BitrixCatalogResult } from '@/types/bitrix';

export async function fetchCatalogItems(
    sectionId: number,
    page: number,
    filter: Record<string, string[]>
): Promise<BitrixCatalogResult> {
    const params = new URLSearchParams({
        SECTION_ID: String(sectionId),
        PAGE_NUM:   String(page),
        sessid:     BX.bitrix_sessid(),
        action:     'getCatalogItems',
    });

    Object.entries(filter).forEach(([key, values]) => {
        values.forEach(val => params.append(`filter[${key}][]`, val));
    });

    const response = await fetch('/local/ajax/catalog.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body:    params.toString(),
    });

    if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
    }

    const json: BitrixAjaxResponse<BitrixCatalogResult> = await response.json();

    if (json.status !== 'success') {
        throw new Error(json.errors?.[0]?.message ?? 'Unknown error');
    }

    return json.data;
}

BX.bitrix_sessid() — a method of the Bitrix core. To use it, you need to declare the global type BX.

Global BX Type

// types/globals.d.ts
declare global {
    const BX: {
        bitrix_sessid(): string;
        message(params: Record<string, string>): void;
        bind(el: Element, event: string, fn: (e: Event) => void): void;
    };
}
export {};

What's Included in TypeScript Development for Bitrix?

  • Environment setup (Node.js, Vite, tsconfig).
  • Type descriptions for your project entities (products, orders, users, settings).
  • Migration of existing JS code while preserving functionality.
  • Integration with Bitrix AJAX components.
  • CI/CD configuration for automatic builds.
  • Documentation on type structure and build.
  • Backward compatibility guarantee: after implementation, old PHP code does not require changes.

Work Process: From Audit to Deployment

  1. Audit of existing JS code (how many lines, which integrations, which errors in logs).
  2. Design of type architecture (interfaces for all entities).
  3. Build setup (Vite, tsconfig, paths).
  4. Phased implementation: first critical functions (cart, catalog), then the rest.
  5. Testing: type checking, unit tests for key AJAX calls.
  6. Deployment: compilation to production, script replacement, error monitoring.
Stage What's Included Estimated Time
Audit and typing Description of current errors, creating types for 3–5 entities 1–2 days
Build setup Vite + tsconfig + paths, compiling first feature 4–8 hours
Implementation (1 module) Transfer of critical functionality to TypeScript 2–5 days
Full coverage All JS logic in the project From 1 week

Get a consultation on TypeScript implementation — we'll evaluate your project for free. Contact us to discuss details.

Comparison of JavaScript and TypeScript for Bitrix

Feature JavaScript TypeScript
Typing Dynamic Static
Error detection At runtime At compile time
Autocompletion Limited Full
Refactoring speed Low High
Average bugs per 1000 lines 10–15 2–4

Timelines and How to Evaluate a Project

Timelines vary from 1 day (basic setup) to 3 weeks (full coverage of a large project). Cost is calculated individually after analyzing code complexity and the number of modules. Write to us — we'll conduct a free audit and offer an optimal plan.

Why Implement TypeScript Now?

  • Reduction in debugging time by 30% based on our project experience.
  • Easier onboarding for new developers — types serve as documentation.
  • Increased stability: critical errors don't reach production.
  • Ability to use modern tools (Zod, React) in the Bitrix ecosystem.

Our team is certified 1C-Bitrix specialists with over 10 years of experience. We have implemented TypeScript in more than 50 projects. Contact us to discuss your project — we'll assess the scope and propose concrete steps.

Why does website layout for 1C-Bitrix require professionalism?

Open template.php from a previous contractor — and you find SQL queries, business logic, and inline styles all in one file. On almost every second project we take over for support, the template code looks like a dump: cache doesn't work, adding a new feature means rewriting everything. Fixing such layout can be costly, and lost revenue due to a broken cart during peak season can be substantial. Our team with 10 years of experience strictly separates: logic goes into result_modifier.php or component_epilog.php, presentation into template.php. No CIBlockElement::GetList in templates. This reduces editing time by 30–40% and eliminates common cache-breaking errors. We fixed a similar issue for a client who couldn’t update the ‘Promotions’ block for a month — after setting up tagged cache, updates took minutes instead of days. Want the same results? Get a free audit of your current layout.

How to properly organize component templates?

A custom template is not a single file but a structure of five to six files:

  • template.php — only HTML and output of $arResult
  • result_modifier.php — data preparation, additional queries
  • component_epilog.php — code after caching (counters, dynamic content)
  • style.css and script.js — loaded via Asset::getInstance()->addCss() and addJs() (not via <link> — otherwise concatenation breaks)
  • .parameters.php — visual editor parameters

Example structure for a catalog:

local/templates/your_template/components/bitrix/catalog.section/.default/
├── template.php
├── result_modifier.php
├── component_epilog.php
├── style.css
├── script.js
└── .parameters.php

Typical templates we develop turnkey:

Component What we do
catalog.section and catalog.element View switching (grid/list/table), lazy load for images, srcset for retina
sale.basket.basket AJAX update without reload, mini-cart via sale.basket.basket.line
menu Mega menu with caching by sections, lazy loading of submenus
search.title Autosuggest with 300ms debounce, product previews in dropdown
breadcrumb Microdata BreadcrumbList according to Schema.org

Caching: why does it break and how do we fix it?

Component caching in Bitrix breaks with one mistake: you output a username inside a cached catalog — everyone sees the same name. Solution — use component_epilog.php for dynamic inserts.

Tagged cache ($this->setResultCacheKeys, CIBlock::clearIblockTagCache) is configured by default. Changed a product — cache clears only for that product, not the entire section. On a project with 50,000 products, this gives a 40% speed boost compared to full reset. Official Bitrix documentation recommends using component_epilog.php for dynamic inserts. Real case. A client complained that everyone saw the same cart on the catalog page. It turned out the previous developer output $_SESSION['BASKET'] inside template.php of the catalog.section component. The component was cached for an hour — the cart was frozen. We moved the output to component_epilog.php and configured tagged cache on sale.basket.basket.line. The page didn’t lose speed, the cart became up-to-date. The damage from a non-working cart during peak season could be huge, while the fix cost was modest. Tagged cache reduces page rebuild time by 50× compared to full reset.

CSS approaches: BEM, Tailwind, or hybrid?

For large projects (30+ templates) we use BEM — .product-card__price, .product-card--featured. Styles are isolated, no conflicts. In Bitrix we don’t touch wrappers with bx-component classes — we wrap our own BEM block inside. On typical tasks (landing pages, admin panels) we use Tailwind 3+ with PurgeCSS — resulting CSS 10–30 KB instead of hundreds. Design tokens in tailwind.config.js lock colors, fonts, spacing in one place. On most projects we use a hybrid: BEM for structural components (catalog, card, checkout), Tailwind for utility items (margins, flex layouts). We agree on the boundary with the team in advance.

How do we achieve Core Web Vitals?

Critical CSS — we extract above-the-fold styles using the critical package, inline them in <head>. The rest loads asynchronously via media="print" onload="this.media='all'". LCP on mobile decreases by 1–1.5 seconds.

Images — the main bottleneck. We use <picture> with WebP and JPEG fallback. loading="lazy" for everything below the fold. width and height explicitly set — CLS = 0. A handler in urlrewrite.php generates WebP on the fly.

Minification and compression. CSS and JS via Vite or Bitrix built-in concatenation. Brotli on nginx (brotli_comp_level 6) — 15–20% more efficient than gzip. Static caching: expires 1y + versioning via query string.

For a catalog of 10,000 products, LCP went from 4.2 s to 2.1 s. Conversions improved by 12% after the speed fix. Want similar results? Order a free audit — we’ll evaluate your current layout and propose specific steps.

Deliverables after layout completion

When you order template development or adaptation, you receive:

  • Source files of component templates with separation into template.php, result_modifier.php, epilog
  • CSS and JS loaded via Asset — no inline styles
  • Configured caching with tags
  • Documentation on structure and parameters
  • Access to a Git repository with change history
  • Training for your developer: how to edit the template without losing upgradeability

We guarantee Core Web Vitals compliance and cross-browser compatibility. Each project is assigned a lead engineer with 10+ years of Bitrix experience.

Process:

  1. Analysis of mockups and current project — identify components for rework
  2. Structure design — break the page into BEM blocks
  3. Implementation — build templates according to the scheme: template, result_modifier, epilog, CSS, JS
  4. Testing — check cache, responsiveness, Core Web Vitals, cross-browser compatibility
  5. Deployment — staging, acceptance, production

At each stage you get intermediate results and can make corrections. Contact our team for a project estimate — we’ll provide a timeline and cost within 1–2 days after receiving mockups.

Common mistakes in Bitrix layout

  • SQL queries inside template.php — breaks caching and creates heavy load
  • Inline <style> and <script> — breaks Asset concatenation and slows loading
  • Missing result_modifier.php — logic mixed with presentation
  • Direct $_REQUEST in cached components — user-specific data leaks
  • Not using component_epilog.php for dynamic content — entire cache invalidated on each user action

Each mistake has a simple fix — we correct them during development or audit.

Timelines

Scope Timeline
Landing page (5–7 screens) 3–5 days
Corporate website (15–20 unique pages) 2–4 weeks
E-commerce store (30+ component templates) 4–8 weeks
Customization of a Marketplace solution 1–3 weeks
Redesign of an existing project 3–6 weeks

Ready to improve your layout? Order a preliminary consultation — we’ll calculate timelines and budget individually.