Manejo de Errores y Registros para neverthrow

¿Alguna vez te has encontrado en un proyecto TypeScript usando el patrón Result y has descubierto que, aunque promete manejo de errores con tipos seguros, tu código se llena de comprobaciones repetitivas isErr y de registros inconsistentes? No estás solo. A medida que el código crece, el beneficio del patrón se diluye si no se adopta un estilo funcional y una política de logging coherente. En este artículo explico una solución práctica para simplificar el manejo de errores con neverthrow y recuperar claridad en el código.
Contexto y experiencia personal: hace aproximadamente año y medio descubrí el patrón Result proveniente de la programación funcional y lo adopté para obtener manejo de errores con tipos seguros en TypeScript. Existen varias librerías que siguen la misma idea, como ts-results, neverthrow y proyectos más ambiciosos como Effect. Empecé usando ts-results y luego migré a neverthrow por ser más completo y mantenido. La experiencia en producción mostró que el patrón ayuda a construir aplicaciones más robustas, con mejor observabilidad, políticas de logging consistentes y manejo de errores fiable.
Aproximación inicial: al principio apliqué Result en todas las funciones y métodos y, aunque funcionaba, surgió mucho boilerplate al componer funciones. Al invocar una función desde otra el código acababa con largos bloques de switch para mapear errores y decidir qué registrar y qué propagar. Esto es correcto pero repetitivo y propenso a inconsistencias entre servicios.
Problema principal: en servicios con lógica de negocio compleja, hasta un 80 por ciento del método puede convertirse en manejo de errores repetitivo. Debemos decidir cuando registrar, que datos incluir y qué nivel de severidad usar. Si cada desarrollador aplica una política distinta, las trazas pierden valor. Incluso con asistencia de IA en el editor, estas decisiones repetitivas se pueden implementar mal.
Solución propuesta: para abordar esto desarrollé un helper que centraliza reglas y obliga a manejar todos los casos posibles con seguridad de tipos y autocompletado. Este helper unifica el tipo de error retornado por las funciones Result, ofrece una función Panic para forzar la parada del proceso cuando ocurre una condición crítica, y brinda un errorHandler que pinta las reglas de mapeo y logging. La idea se inspira en la separación que hace Rust entre errores esperables y fallos críticos que requieren detener el servicio o redeploy.
Qué hace el helper y por qué ayuda: primero, estandariza el tipo de error mediante un errorBuilder que provoca que todas las funciones que pueden fallar compartan la misma estructura de errores. Segundo, incluye Panic para situaciones en que la aplicación no puede continuar, por ejemplo validaciones de arranque que detectan una variable de configuración clave ausente o una cadena de conexión a la base de datos vacía. Panic debe usarse con precaución, no para fallos transitorios como una API externa caída temporalmente. Tercero, el errorHandler incluye la lógica para traducir códigos de error, registrar de forma consistente y construir el objeto error que la función debe devolver.
Reglas que implementa el handler: los reservedErrorCodes se traducen automáticamente a UNEXPECTED_ERROR y se consideran errores no críticos pero inesperados; en ese caso el handler asegura que el fallo se registre en detalle una sola vez y el error se propague como UNEXPECTED_ERROR por todas las capas. Cuando un error esperado se mapea a otro error esperado, se registra a nivel info o log para ayudar a seguir la ejecución sin ruido. Si un error esperado se traduce a UNEXPECTED_ERROR, se registra a nivel error con todos los datos disponibles porque indica una condición que no debería ocurrir. Si un mapeo produce PANIC, el handler invoca Panic para finalizar el proceso y dejar que las herramientas de observabilidad y la plataforma de despliegue se encarguen de notificar y redeployar la última versión estable.
Uso práctico: en lugar de escribir largos switches, la función llamante puede delegar en errorHandlerResult pasando el error recibido, la instancia de logger y un mapa que exige cubrir todos los códigos de error posibles. El compilador obliga a manejar cada caso y proporciona autocompletado para los códigos y los datos adicionales a registrar. Con esto se elimina gran parte del boilerplate de manejo de errores y se unifica el formato y niveles de logging de forma centralizada. Además hay una variante raw del handler que puede usarse dentro de transformaciones funcionales como map de neverthrow.
Beneficios: menos código repetitivo, logging uniforme y fácil de mantener, posibilidad de cambiar políticas de registro en un único lugar, y mayor observabilidad en producción. Esto facilita también cumplir requisitos de seguridad y auditoría cuando se registran errores sensibles de forma controlada.
Recomendaciones prácticas: siempre pasar la instancia de logger al handler para integrarlo con soluciones como pino o similares. Implementar un correlationId para seguir trazas entre servicios. Registrar a nivel log o info todas las mutaciones importantes con un formato consistente, por ejemplo logger.log con los parámetros relevantes. Evitar Panic para fallos transitorios y reservarlo para condiciones irreparables durante la inicialización o para corrupción crítica.
Sobre Q2BSTUDIO: en Q2BSTUDIO somos una empresa de desarrollo de software y aplicaciones a medida que ayuda a empresas a construir soluciones robustas y observables. Somos especialistas en software a medida, inteligencia artificial y ciberseguridad, y ofrecemos servicios cloud aws y azure, servicios de inteligencia de negocio y soluciones con power bi. Si necesitas desarrollar una plataforma o una app empresarial a medida visita nuestra página de desarrollo de aplicaciones y software a medida y descubre nuestros servicios. También trabajamos proyectos de inteligencia artificial para empresas y agentes IA, puedes conocer nuestras propuestas de Inteligencia artificial para empresas.
Conclusión: centralizar el manejo de errores y el logging con un helper que use el patrón Result de neverthrow reduce el ruido, evita duplicación y mejora la trazabilidad y la resiliencia de tus servicios. Si te interesa que llevemos esta práctica a tu proyecto, en Q2BSTUDIO podemos ayudar con arquitectura, implementación y con la integración de observabilidad y seguridad para que tu producto cumpla con los requisitos operativos y regulatorios. Palabras clave que aplicamos en nuestros proyectos: aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA y power bi.
Si te interesa convertir el helper en un paquete npm o adaptar su política de logging a otra metodología, coméntanos y evaluamos cómo colaborar para llevarlo a producción en tu organización.
Comentarios