Типизация data-атрибутов и Dataset API — type-safe селекторы без рантайм-багов
Типизация data-атрибутов и Dataset API — type-safe селекторы без рантайм-багов Data-атрибуты — мощный инструмент для связывания разметки, JS и CSS. Но без типов легко опечататься в data-modal-id или забыть синхронизировать CSS-селектор с JS. В большом проекте это приводит к багам, которые невозможно поймать до тестирования. Как это выглядит в production Опишите контракт через TypeScript template literal types: type DataAttributes = { 'modal-id': 'header' | 'footer'; 'theme': 'light' | 'dark'; 'row-index': number; }; Затем генерируйте type-safe селекторы: type DataSelector<T extends keyof DataAttributes> = [data-${T}=&quot;${DataAttributes[T]}&quot;]; const headerSelector: DataSelector<'modal-id'> = '[data-modal-id="header"]'; // OK Dataset API с маппингом Создайте функцию, которая приводит к camelCase и проверяет типы: function getDataset<K extends keyof DataAttributes>(el: HTMLElement, attr: K): DataAttributes[K] { const key = attr.replace(/[A-Z]/g, m => -${m.toLowerCase()}); return el.dataset[key] as DataAttributes[K]; } Ошибка: забыть, что data-modal-id в dataset становится modalId. Теперь IDE подсветит невалидные ключи. CSS-переменные из типов Соберите CSS custom properties автоматически: const cssVar = --${headerSelector.replace(/[\[\]=&quot;]/g, '').replace(/\s/g, '-')}; // получите --data-modal-id-header Практические советы - Добавьте eslint-правило, запрещающее querySelector('[data-*]') без типов. Это ловится статическим анализом. - Для больших проектов используйте генерацию схемы из единого источника (например, JSON Schema) и экспорт типов — это защитит от рассинхронизации с дизайном. Вывод: Типизация data-атрибутов через template literal types превращает runtime-ошибки в compile-time, синхронизирует CSS и JS, и снижает когнитивную нагрузку при разработке.