
Escuchar este post
Selecciona una voz y genera audio para escuchar este post
Cuando trabajas con Effect.gen
, es común encontrarse con dos sintaxis diferentes para manejar efectos. Una usa yield*
directamente, y otra lo utiliza también pero con un parámetro adaptador representado comúnmente como _
. Te explico todo sobre esta característica aquí. 👽
¿Qué es el Parámetro Adaptador?
El parámetro adaptador es una función que Effect.js proporciona como segundo parámetro en tu función generadora, permitiéndote ejecutar efectos de manera más explícita
:
// Sintaxis tradicional con yield* Effect.gen(function* () { const config = yield* WhatsAppConfigSchema }) // Sintaxis con adaptador (_) Effect.gen(function* (_) { const config = yield* _(WhatsAppConfigSchema) })
Comparación de Sintaxis
Ambas sintaxis son funcionalmente idénticas y producen exactamente el mismo resultado:
| Método | Sintaxis | Ejemplo | | --- | --- | --- | | **Tradicional** | `yield* efecto` | `yield* Effect.succeed(42)` | | **Con Adaptador** | `yield* _(efecto)` | `yield* _(Effect.succeed(42))` |
Ejemplo Práctico: Configuración de WhatsApp
Veamos un ejemplo real que muestra ambas sintaxis:
import { Effect, Config } from "effect" // Schema de configuración const WhatsAppConfigSchema = Config.object({ apiKey: Config.string("WHATSAPP_API_KEY"), phoneNumber: Config.string("WHATSAPP_PHONE"), webhookUrl: Config.string("WHATSAPP_WEBHOOK_URL") }) // Versión tradicional const setupWhatsAppTraditional = Effect.gen(function* () { const config = yield* WhatsAppConfigSchema const client = yield* createWhatsAppClient(config) const webhook = yield* setupWebhook(config.webhookUrl) yield* Effect.log(`WhatsApp configurado para: ${config.phoneNumber}`) return { client, webhook, config } }) // Versión con adaptador const setupWhatsAppWithAdapter = Effect.gen(function* (_) { const config = yield* _(WhatsAppConfigSchema) const client = yield* _(createWhatsAppClient(config)) const webhook = yield* _(setupWebhook(config.webhookUrl)) yield* _(Effect.log(`WhatsApp configurado para: ${config.phoneNumber}`)) return { client, webhook, config } })
¿Por Qué Usar el Adaptador?
1. Claridad Visual y Explicitez
El adaptador hace más obvio que estás "ejecutando" un efecto:
Effect.gen(function* (_) { // Es muy claro que estas líneas ejecutan efectos const user = yield* _(getUserById("123")) const profile = yield* _(getProfile(user.id)) const settings = yield* _(getSettings(profile.id)) return { user, profile, settings } })
2. Compatibilidad con Herramientas
Algunas herramientas de análisis estático, linters o IDEs pueden manejar mejor la sintaxis con paréntesis:
// Algunas herramientas prefieren esto yield* _(Effect.tryPromise(() => fetch('/api/data'))) // Sobre esto yield* Effect.tryPromise(() => fetch('/api/data'))
3. Consistencia de Estilo
Algunos equipos adoptan esta sintaxis por consistencia y legibilidad:
Effect.gen(function* (_) { yield* _(Effect.log("Iniciando proceso")) const data = yield* _(fetchData()) const processed = yield* _(processData(data)) const result = yield* _(saveResult(processed)) yield* _(Effect.log("Proceso completado")) return result })
Ejemplo Complejo: Pipeline de Procesamiento
import { Effect, pipe } from "effect" interface ProcessingConfig { batchSize: number retryAttempts: number timeout: string } const processDataPipeline = (config: ProcessingConfig) => Effect.gen(function* (_) { yield* _(Effect.log("🚀 Iniciando pipeline de procesamiento")) // Configuración inicial const startTime = yield* _(Effect.sync(() => Date.now())) // Obtener datos const rawData = yield* _(fetchRawData(config.batchSize)) yield* _(Effect.log(`📥 Obtenidos ${rawData.length} registros`)) // Procesar en lotes const processedBatches = yield* _( Effect.forEach( rawData, (batch) => processBatch(batch, config.retryAttempts), { concurrency: "unbounded" } ) ) // Consolidar resultados const finalResult = yield* _(consolidateResults(processedBatches)) // Métricas finales const endTime = yield* _(Effect.sync(() => Date.now())) const duration = endTime - startTime yield* _(Effect.log(`✅ Pipeline completado en ${duration}ms`)) yield* _(Effect.log(`📊 Procesados ${finalResult.totalRecords} registros`)) return finalResult })
Firma de Tipos del Adaptador
La función adaptador tiene esta firma:
type Adapter = <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
Es simplemente una función identidad que toma un efecto y devuelve el mismo efecto, pero proporciona una sintaxis más explícita. ✅
¿Cuál Sintaxis Elegir?
La elección entre ambas sintaxis es principalmente preferencia personal o convención de equipo:
Sintaxis Tradicional (sin adaptador)
Ventajas:
- Más concisa y limpia
- Menos caracteres para escribir
- Sintaxis más directa
Cuándo usarla:
- Proyectos personales o equipos que prefieren concisión
- Cuando la legibilidad no se ve comprometida
- Para efectos simples y directos
Sintaxis con Adaptador
Ventajas:
- Más explícita sobre la ejecución de efectos
- Mejor compatibilidad con algunas herramientas
- Consistencia visual en pipelines complejos
- Más clara para desarrolladores nuevos en Effect
Cuándo usarla:
- Equipos que valoran la explicitez
- Pipelines complejos con muchos efectos
- Cuando se trabaja con herramientas que prefieren esta sintaxis
- Proyectos donde la claridad es prioritaria
Consideraciones de TypeScript
Para usar cualquiera de las dos sintaxis correctamente, asegúrate de tener la configuración adecuada:
{ "compilerOptions": { "target": "es2015", // o superior "strict": true, // recomendado para mejor tipado "downlevelIteration": true // si usas target < es2015 } }
Recomendaciones Prácticas
- Mantén consistencia en tu proyecto - elige una sintaxis y úsala en todo el código
- Considera tu equipo - la sintaxis con adaptador puede ser más clara para principiantes
- Evalúa la complejidad - pipelines complejos pueden beneficiarse del adaptador
- Prueba ambas - experimenta para ver cuál se siente más natural
El parámetro adaptador (_
) en Effect.gen
es una característica elegante que proporciona una sintaxis alternativa para ejecutar efectos. 🧪
Aunque funcionalmente idéntica a la sintaxis tradicional con yield*
, ofrece ventajas en términos de claridad, explicitez y compatibilidad con herramientas.
La elección entre ambas sintaxis depende de tus preferencias personales, las convenciones de tu equipo y la complejidad de tus pipelines de efectos. Lo importante es mantener consistencia y elegir la opción que haga tu código más legible y mantenible.
¿Te gustó este artículo? Compártelo con otros desarrolladores que puedan beneficiarse de aprender sobre Effect Generators.
Abrazo. Bliss. 🤓
Enlaces relacionados

Astro. ¿Otro framework JavaScript?
Checa este otro Post
