Tu graduación como maquetador con red de seguridad: tomar la página viva
del módulo 14 —scroll reveals, navbar inteligente y modal accesible— y
migrarla a TypeScript estricto, sin un solo error del compilador. El
resultado se ve y se comporta IGUAL; la diferencia es que ahora es
imposible que un null o un typo la rompan sin que tú lo sepas antes.
Reto
La página viva, ahora tipada
Media60 min60 XP(×2 sin mirar la solución)
Qué debes construir
Migra tu proyecto del módulo 14 (o el de referencia de su reto) a un Vite
vanilla-ts, con "strict": true, hasta que tsc no reporte NINGÚN error.
Requisitos:
Todos los elementos tipados: querySelector<...> con el tipo
correcto, querySelectorAll<HTMLElement> para las colecciones.
Todos los null manejados: sin ! gratuitos; usa null-guards
(if) u optional chaining donde corresponda.
Eventos tipados: aprovecha la inferencia (KeyboardEvent en
keydown) y castea event.target cuando haga falta.
Cero errores en modo estricto: npx tsc --noEmit limpio.
Mismo comportamiento y misma accesibilidad que el original (reveals con
reduced-motion, navbar, modal con foco/Escape).
Reglas
Vite vanilla-ts, tsconfig estricto.
Nada de any (romperías el propósito) ni // @ts-ignore para tapar
errores: resuélvelos de verdad.
El ! (non-null assertion) solo si de verdad no hay forma de que sea
null y lo justificas; preferir el if.
60:00
Cuando estés listo, arranca el reloj.
El razonamiento — migrar bien es un proceso mecánico y agradable:
Tipa primero, deja que aparezcan los errores. Al poner los tipos en
la selección, TypeScript ilumina cada null sin manejar. No los buscas:
te los muestra. Vas apagando cada rojo con un guard o un ?..
Un null-guard por bloque, no aserciones sueltas. Envolver el modal en
if (abrir && modal && cerrar) limpia de golpe los tres, sin ! por
todos lados. El código queda idéntico al del módulo 14 pero seguro.
Confía en la inferencia. No tipas los eventos a mano: addEventListener
ya sabe que keydown da KeyboardEvent. Solo casteas event.target
cuando lo necesites. TypeScript trabaja PARA ti, no te estorba.
Y corriendo (el JavaScript compilado — mismo comportamiento):
<header class="navbar" id="navbar"><span class="logo">Forge</span><button class="btn" id="abrir">Suscríbete</button></header><section class="hero" id="hero"><h1>Página viva, tipada</h1><p>Baja para los reveals. "Suscríbete" abre el modal.</p></section><section class="bloque revelar"><h2>Reveal 1</h2><p>Aparezco al entrar en pantalla.</p></section><section class="bloque revelar"><h2>Reveal 2</h2><p>El navbar de arriba ya se compactó.</p></section><section class="bloque revelar"><h2>Reveal 3</h2><p>Mismo JS del módulo 14, escrito con red de seguridad.</p></section><div class="modal" id="modal" role="dialog" aria-modal="true" aria-labelledby="mt" aria-hidden="true"><div class="dialogo"><h2 id="mt">Suscríbete</h2><p>Cierra con el botón, Escape o el fondo.</p><button class="btn" id="cerrar">Listo</button></div></div>
Autoevaluación: ¿npx tsc --noEmit sale limpio? ¿Cada elemento tiene su
tipo y cada null su guard (sin ! gratuitos ni any)? ¿La página se
comporta idéntica a la del módulo 14? Tres síes: migraste a TypeScript
estricto, la habilidad que el brief marca como imprescindible.
Qué sigue
Módulo 15 cerrado: escribes interfaces con red de seguridad, del DOM a los
datos. El módulo 16 cambia de disciplina y sube el techo creativo al
máximo: GSAP, la librería de animación con la que se hacen los sitios
premiados en Awwwards. Timelines, ScrollTrigger y scrollytelling — cuando
el CSS del módulo 11 ya no alcanza, empieza GSAP.