TypeScript y Accesibilidad: cómo escribir código accesible para todos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Por qué la Accesibilidad no es sobre "marcar casillas", sino sobre personas

\n

Seamos honestos: cuando escuchamos "accesibilidad" (o a11y), muchos de nosotros imaginamos listas interminables de requisitos, revisiones aburridas y la frase "bueno, esto es para personas con discapacidades". Pero la verdad es que la accesibilidad es para todos. ¿Alguna vez has intentado pedir una pizza mientras caminas, sosteniendo el teléfono con una sola mano? ¿O has estado en el metro con mala conexión a internet, donde el sitio tarda una eternidad en cargar? Eso son problemas de accesibilidad.

\n

En este artículo hablaremos de cómo TypeScript puede convertirse en tu mejor amigo para crear aplicaciones web accesibles. No solo "agregar etiquetas", sino construir una arquitectura donde la inclusividad no sea una característica, sino la base.

\n\n

TypeScript como escudo contra errores de a11y

\n

Muchos piensan que TypeScript es solo sobre tipos de datos y protección contra errores. Pero en realidad, la tipificación estricta también puede ayudar en cuestiones de accesibilidad. Analicemos con ejemplos.

\n\n

Tipificación de atributos ARIA

\n

Uno de los problemas más comunes son los valores incorrectos de los atributos ARIA. ¿Alguna vez has escrito role="button" en un div? ¿Y luego olvidaste agregar tabindex? TypeScript puede detectar esto en tiempo de compilación.

\n
// Mal: sin protección alguna\nfunction createButton(label: string) {\n  return `<div role="button">${label}</div>`;\n}\n\n// Bien: tipificamos ARIA\ntype AriaRole = 'button' | 'navigation' | 'alert' | 'dialog';\n\ninterface AriaAttributes {\n  role: AriaRole;\n  'aria-label'?: string;\n  'aria-expanded'?: boolean;\n  tabIndex?: number;\n}\n\nfunction createAccessibleButton(label: string, aria: AriaAttributes) {\n  // Ahora TypeScript verificará que el rol sea válido\n  return {\n    tag: 'div',\n    attrs: aria,\n    content: label\n  };\n}\n\n// ¡Error! 'btn' no está incluido en el tipo AriaRole\n// createAccessibleButton('Haz clic en mí', { role: 'btn' });
\n

¿Notas la diferencia? TypeScript no te permitirá escribir accidentalmente role="btutton" u olvidar un atributo obligatorio. Es como un asistente personal que susurra: "Oye, ¿estás seguro de que esto es accesible?"

\n\n

Verificación estricta de estados de enfoque

\n

Otro dolor de cabeza es la gestión del foco. Especialmente en SPA, donde la página no se recarga. TypeScript ayuda a crear envoltorios seguros.

\n
// Definimos qué elementos pueden recibir el foco\ntype FocusableElement = HTMLInputElement | HTMLButtonElement | HTMLAnchorElement | HTMLSelectElement | HTMLTextAreaElement;\n\nfunction safelySetFocus(element: FocusableElement | null): void {\n  if (element && document.contains(element)) {\n    element.focus();\n  } else {\n    console.warn('El elemento no se encuentra en el DOM o no puede recibir el foco');\n  }\n}\n\n// Uso\nconst modal = document.querySelector('.modal__close-btn');\nsafelySetFocus(modal as FocusableElement | null);
\n

Observa: no solo llamamos a .focus(), sino que verificamos si el elemento existe y si puede ser enfocado. Esto previene errores que podrían dejar al usuario de un lector de pantalla en el vacío.

\n\n

Construyendo una arquitectura con a11y como base

\n

Ahora pasemos a cosas más avanzadas. ¿Cómo lograr que la accesibilidad esté integrada en la arquitectura de tu proyecto, y no añadida "a última hora" antes del lanzamiento?

\n\n

Props tipificados para componentes

\n

Crea una interfaz base para todos tus componentes. Es como una constitución para la accesibilidad.

\n
// Interfaz base para todos los componentes UI\ninterface AccessibleComponentProps {\n  id?: string;\n  className?: string;\n  ariaLabel?: string;\n  ariaDescribedby?: string;\n  role?: string;\n  tabIndex?: number;\n  isDisabled?: boolean;\n  onClick?: () => void;\n  onKeyDown?: (e: React.KeyboardEvent) => void;\n}\n\n// Componente de botón específico\ninterface ButtonProps extends AccessibleComponentProps {\n  variant                

Blogs

Book Recommendations