Alejandría

Busca en Alejandría

Lenguajes y marcos

Effect

Biblioteca TypeScript para modelar efectos, errores, dependencias y concurrencia de forma componible.

01

En pocas palabras

Biblioteca TypeScript para modelar efectos, errores, dependencias y concurrencia de forma componible.

Qué problema resuelve

Flujos asíncronos complejos con errores y limpieza de recursos difíciles de coordinar.

Cuándo utilizarlo

Servicios con integración y resiliencia. Ejemplo: consultar varias fuentes con timeout y política de reintento.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

En el Radar compartido: Trial (valoración de la edición aportada).

Cómo funciona

Representa cálculos como valores que describen resultado, error y requisitos. La ejecución controla aspectos como cancelación, adquisición de recursos y composición.

Ejemplo de uso

Describir una consulta externa con error tipado y timeout. Aplicar reintentos solo a fallos transitorios y proporcionar una dependencia simulada para probar cada ruta.

El tipo Effect<A, E, R>

Parámetro Significado
A Valor que produce si tiene éxito
E Errores esperados, tipados
R Dependencias (servicios) que necesita

A diferencia de una Promise, un Effect es una descripción perezosa: no se ejecuta hasta que se corre explícitamente, lo que permite componer reintentos, timeouts y dependencias antes de ejecutar.

Ejemplo: cliente del buró con errores, reintentos y dependencias

import { Context, Data, Effect, Layer, Schedule } from 'effect';

class BuroError extends Data.TaggedError('BuroError')<{ status: number }> {}

class Buro extends Context.Tag('Buro')<
  Buro,
  { consultar: (documento: string) => Effect.Effect<Historial, BuroError> }
>() {}

const evaluar = (documento: string) =>
  Effect.gen(function* () {
    const buro = yield* Buro;
    const historial = yield* buro.consultar(documento);
    return calcularPuntaje(historial);
  }).pipe(
    Effect.timeout('3 seconds'),
    Effect.retry({
      schedule: Schedule.exponential('200 millis'),
      times: 2,
      while: (e) => e._tag === 'BuroError' && e.status >= 500,
    }),
    Effect.catchTag('TimeoutException', () =>
      Effect.succeed(PUNTAJE_PENDIENTE),
    ),
  );

const BuroHttp = Layer.succeed(Buro, {
  consultar: (doc) => llamarApiBuro(doc),
});

Effect.runPromise(evaluar('123456').pipe(Effect.provide(BuroHttp)));

El tipo de evaluar indica, sin leer la implementación, que puede fallar con BuroError y que necesita un Buro. En las pruebas se proporciona otra Layer con un buró simulado.

Ecosistema

Módulo Para qué
Schema Validación y transformación de datos con tipos inferidos
Stream Flujos de datos con control de recursos y backpressure
Fiber Concurrencia estructurada con cancelación
@effect/platform HTTP, sistema de archivos, terminal, multiplataforma
@effect/sql Acceso a bases de datos
@effect/opentelemetry Trazas automáticas de cada efecto

Adopción gradual

  1. Empieza en el borde con más fallos: integraciones externas con reintentos y timeouts.
  2. Mantén una frontera clara: funciones que devuelven Promise hacia el resto del código (Effect.runPromise).
  3. Forma al equipo con ejemplos internos; la curva de aprendizaje es real.
  4. Amplía a otros módulos si los beneficios (errores explícitos, testabilidad) compensan.

Para equipos que solo necesitan validación, Zod o Schema por separado pueden bastar; Effect compensa cuando la complejidad está en la orquestación de efectos y errores. Ver patrones de resiliencia.

Criterios de implementación

Evitar reintentar operaciones no idempotentes sin protección. Definir fronteras con código Promise existente y revisar propagación de errores y finalización de recursos.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.