Дженерики и утилиты типов

aria-query — это JavaScript-библиотека, предназначенная для работы с ARIA-атрибутами, их значениями и схемами ролей. Она обеспечивает строгую типизацию и проверку соответствия ARIA-спецификациям, позволяя создавать инструменты для доступности интерфейсов, валидаторы и статический анализ кода. Библиотека предоставляет данные о ролях, их свойствах, возможных атрибутах и поддерживаемых состояниях, а также позволяет проверять правильность применения ARIA-атрибутов в DOM.

Структура данных

Главные экспортируемые объекты:

  1. Roles Представляет собой маппинг ARIA-ролей к их характеристикам. Каждая роль описывается следующими свойствами:

    • name: имя роли, например, "button".
    • abstract: булевое значение, определяет абстрактные роли, которые нельзя использовать напрямую в DOM.
    • superClass: массив родительских ролей, унаследованных от этой роли.
    • props: объект с описанием допустимых ARIA-свойств для роли, включая типы и допустимые значения.
  2. Elements Маппинг HTML-элементов на роли. Например, <button> может иметь роль "button". Это используется для проверки соответствия семантики и ARIA-ролей.

  3. Attributes Содержит информацию обо всех ARIA-атрибутах: допустимые значения, типы (string, boolean, token и массивы токенов).

Работа с ролями

Для работы с ролями библиотека предоставляет несколько утилит:

  • getRoles(): возвращает объект с описанием всех ролей и их свойств.
  • getRole(roleName): возвращает объект роли по имени. Если роль не существует, возвращает undefined.
  • isAbstractRole(roleName): проверяет, является ли роль абстрактной.

Пример:

import { getRoles, getRole } from 'aria-query';

const buttonRole = getRole('button');

console.log(buttonRole.abstract); // false
console.log(buttonRole.superClass); // ['command', 'widget']
console.log(Object.keys(buttonRole.props)); // список допустимых ARIA-свойств

Работа с элементами

aria-query позволяет получать маппинг между HTML-элементами и ролями, что полезно для статического анализа. Основные функции:

  • getElementRoles(elementName): возвращает массив ролей, которые может иметь данный HTML-элемент.
  • getElementsForRole(roleName): возвращает массив элементов, для которых роль разрешена.

Пример:

import { getElementRoles } from 'aria-query';

const rolesForButton = getElementRoles('button');
console.log(rolesForButton); // ['button', 'menuitem', 'tab']

Типы и утилиты

Библиотека предоставляет строгую типизацию, особенно при использовании TypeScript. Основные интерфейсы:

  • Role: описывает роль, ее свойства, атрибуты и наследование.
  • ElementRoleMap: маппинг элементов к массиву ролей.
  • Attribute: описание ARIA-атрибута, включая допустимые значения и тип.

Утилиты для работы с типами включают:

  • isDefinedRole(roleName: string): roleName is keyof Roles — позволяет TypeScript определить корректную роль на этапе компиляции.
  • isAbstractRole(roleName: string): boolean — проверка абстрактности роли.
  • getImplicitAriaRoles(elementName: string) — возвращает роли, которые применяются по умолчанию для данного HTML-элемента.

Проверка атрибутов

Для каждой роли библиотека хранит информацию о свойствах и типах ARIA-атрибутов. Примеры типов:

  • Boolean: атрибуты типа aria-hidden, aria-disabled.
  • String: aria-label, aria-placeholder.
  • Token: ограниченный набор значений, например aria-sort может принимать "none" | "ascending" | "descending" | "other".
  • TokenList: массив токенов, например aria-owns.

Проверка значений:

import { getRole } from 'aria-query';

const gridRole = getRole('grid');
const ariaSortable = gridRole.props['aria-sort'];

console.log(ariaSortable.type); // 'token'
console.log(ariaSortable.values); // ['none', 'ascending', 'descending', 'other']

Расширение и кастомизация

Хотя aria-query ориентирована на официальные спецификации ARIA, структура позволяет создавать свои расширения:

  • Добавление кастомных ролей через Map или обертки над getRoles().
  • Фильтрация ролей по поддерживаемым элементам или абстрактности.
  • Создание статических проверок на этапе сборки для библиотек UI.

Интеграция с TypeScript

Использование TypeScript повышает надежность. Типы ролей и атрибутов позволяют:

  • Автодополнение при работе с ролями.
  • Проверку корректности значения ARIA-атрибутов во время компиляции.
  • Предотвращение использования абстрактных ролей в DOM.

Пример типизированного использования:

import { getRole } from 'aria-query';
import type { Role } from 'aria-query';

const roleName: keyof Role = 'button';
const role = getRole(roleName);

if (role && !role.abstract) {
  // безопасно использовать роль в DOM
}

Практическое применение

  • Линтеры для доступности: eslint-plugin-jsx-a11y использует данные из aria-query для проверки React-компонентов.
  • Статический анализ: генерация отчетов о некорректных ARIA-атрибутах в кодовой базе.
  • Автогенерация документации: построение схем ролей и поддерживаемых атрибутов для компонентов UI.

aria-query служит связующим звеном между спецификациями ARIA и практическим кодом, предоставляя строгие типы и богатые утилиты для анализа и проверки доступности интерфейсов. Она упрощает интеграцию стандартов доступности в современные JavaScript-приложения, особенно в средах с динамическими интерфейсами, таких как React, Vue или Angular.