Volver a Últimas PublicacionesBlog

Mejores Practicas de TypeScript para Desarrollo Fullstack

Por Carlos Diaz · 22 de noviembre de 2024 · 3 min de lectura

Recuerdo claramente un incidente de produccion que involucraba una funcion que recibia un objeto de orden con un campo status que en teoria podia ser una de seis cadenas de texto, pero el codigo solo manejaba cuatro de ellas. Los otros dos eran estados validos que simplemente habiamos olvidado. Ese bug no existe en una base de codigo que modela el estado con uniones discriminadas en lugar de strings sueltos, y ese es el patron que mas ha hecho por la calidad de mi codigo que cualquier otra tecnica de TypeScript.

Una union discriminada te obliga a manejar cada caso explicitamente, porque el compilador no dejara compilar un switch si falta una variante y tienes el modo strict y las verificaciones de exhaustividad activadas. La misma idea se extiende al modelado de dominio con tipos de marca: que una direccion de correo, un ID de usuario y un string cualquiera se representen todos como string es exactamente como terminas pasando el valor equivocado a la funcion equivocada sin que el compilador ni una prueba lo detecten. Marcar estos tipos no cuesta nada en tiempo de ejecucion y detecta una categoria entera de errores a nivel de tipos.

Los genericos merecen mas cuidado del que normalmente reciben en codigo de aplicacion. Una funcion generica utilitaria tipada de forma laxa que acepta any internamente es apenas mas util que no tener tipos - el valor viene de restringir el generico lo suficiente para que el compilador pueda verificar que la funcion se comporta correctamente para cada tipo que satisface la restriccion, no solo el que probaste.

La practica de mayor impacto, sin embargo, es compartir tipos en todo el stack. Cuando tu capa de API y tu frontend consumen los mismos tipos generados - ya sea a traves de un paquete compartido en un monorepo, un cliente generado desde OpenAPI o un setup de GraphQL codegen - un cambio en la API que rompe el frontend aparece como un error de compilacion en CI, no como un bug en produccion que reporta un usuario. Esa sola practica ha atrapado mas bugs de integracion en mis equipos que cualquier cantidad de disciplina de pruebas manuales.

Nada de esto se trata de perseguir la seguridad de tipos por si misma. Cada uno de estos patrones existe porque elimino una categoria de bugs reales en una base de codigo real, y esa es la vara con la que mido cualquier patron nuevo de TypeScript antes de introducirlo a un equipo.

Puntos Clave

  • Las uniones discriminadas hacen que los estados invalidos de la aplicacion sean irrepresentables y fuerzan un manejo exhaustivo.
  • Los tipos de marca agregan seguridad a nivel de dominio sin costo en tiempo de ejecucion.
  • Las restricciones genericas estrictas mantienen las utilidades reutilizables seguras de punta a punta, no solo para el tipo que probaste.
  • Compartir tipos generados entre frontend y backend detecta errores de integracion en tiempo de compilacion.
  • Cada patron de seguridad de tipos debe ganarse su lugar eliminando una categoria real de bugs, no por moda.