Volver al blog

La función más importante de mi código

5 Octubre 2025
6 min de lectura
Patrón Result en TypeScript

La función más importante de mi código

Después de años escribiendo TypeScript, hay una función que se ha convertido en el pilar fundamental de todos mis proyectos. No es una librería compleja ni un framework de moda. Son apenas 15 líneas de código que han transformado completamente la forma en que manejo errores.

El problema que todos ignoramos

Seamos honestos: el manejo de errores en JavaScript es un desastre esperando a ocurrir. Lanzamos excepciones como si fueran confeti y luego nos preguntamos por qué nuestra aplicación se cae en producción.

// Código que todos hemos escrito

async function getUser(id: string) {

const response = await fetch(/api/users/${id});

const user = await response.json(); // 💥 ¿Y si falla?

return user;

}

¿Qué pasa si la red falla? ¿Si el servidor devuelve un 500? ¿Si el JSON está corrupto? Excepciones volando por todos lados, sin control, sin tipos, sin predictibilidad.

La solución: el patrón Result

Inspirado en lenguajes como Rust y Haskell, implementé una versión simple pero poderosa del patrón Result en TypeScript:

type Success = { data: T; error: null };

type Failure = { data: null; error: E };

type Result = Success | Failure;

export async function tryCatch(

promise: Promise,

): Promise> {

try {

const data = await promise;

return { data, error: null };

} catch (error) {

return { data: null, error: error as E };

}

}

¿Por qué es tan importante?

1. Type-safety real

TypeScript entiende perfectamente el flujo de control:

const result = await tryCatch(fetchUser(id));

if (result.error) {

// TypeScript sabe que result.data es null aquí

console.error(result.error);

return;

}

// TypeScript sabe que result.error es null aquí

const user = result.data; // ✅ Tipo correcto, sin casts

2. Errores explícitos

No más sorpresas. Cada llamada que puede fallar lo declara abiertamente:

// Antes: ¿Puede fallar? ¿Quién sabe? 🤷‍♂️

const user = await getUser(id);

// Ahora: Claramente puede fallar

const result = await tryCatch(getUser(id));

3. Composición elegante

Encadenar operaciones que pueden fallar se vuelve natural:

async function getUserPosts(userId: string) {

const userResult = await tryCatch(fetchUser(userId));

if (userResult.error) return userResult;

const postsResult = await tryCatch(fetchPosts(userResult.data.id));

if (postsResult.error) return postsResult;

return { data: postsResult.data, error: null };

}

4. Debugging simplificado

Cuando algo falla, sabes exactamente dónde y por qué. No más stack traces perdidos o excepciones sin capturar.

Casos de uso reales

API calls

const result = await tryCatch(

fetch('/api/data').then(r => r.json())

);

if (result.error) {

toast.error('Error al cargar los datos');

return;

}

setData(result.data);

Validación de datos

const parseResult = await tryCatch(

validateSchema(input)

);

if (parseResult.error) {

return {

success: false,

errors: parseResult.error.errors

};

}

Operaciones de base de datos

const dbResult = await tryCatch(

db.user.create({ data: userData })

);

if (dbResult.error) {

logger.error('DB Error:', dbResult.error);

throw new DatabaseException();

}

return dbResult.data;

El impacto en mi código

Desde que adopté este patrón:

  • Cero errores sin capturar en producción relacionados con promesas
  • Menos bugs porque el compilador me obliga a manejar errores
  • Código más legible porque el flujo de error es explícito
  • Refactoring más seguro porque los tipos guían los cambios
  • No necesitas una librería

    He visto librerías como neverthrow o ts-results que implementan este patrón con características adicionales. Son excelentes, pero para la mayoría de casos, estas 15 líneas son suficientes.

    La simplicidad es poder. Puedes copiar esta función, entenderla completamente, modificarla si necesitas, y no agregar una dependencia más a tu package.json.

    Conclusión

    Esta función no es mágica. No va a resolver todos tus problemas. Pero te obligará a pensar en los errores como ciudadanos de primera clase en tu código, no como efectos secundarios molestos.

    Y esa mentalidad, ese cambio de paradigma, es lo que realmente transforma la calidad de tu código.

    ¿La mejor parte? Una vez que empiezas a usarla, nunca vuelves atrás.

    ¿Te ha gustado este artículo?

    📬 ¡ÚNETE A MI NEWSLETTER! 📬

    ¡No te pierdas ningún contenido exclusivo! Comparto regularmente consejos, tutoriales y reflexiones sobre programación, desarrollo web y tecnología que no encontrarás en ningún otro lugar.

    🔥 SUSCRÍBETE AHORA 🔥