Write idiomatic modern Effect TypeScript using Effect.gen or clear pipelines, typed error channels, Context and Layer services, and resource-safe runtime boundaries. Use when building or reviewing code with Effect, @effect/platform, Schema, Layers, or Effect-based applications.
Use this skill to keep Effect code modern, explicit, and faithful to the library's model instead of falling back to Promise-first habits.
Effect code should make three things obvious from the type and structure:
Prefer Effect-native modeling over wrapping Promise code and keeping the old design.
Effect.gen for multi-step workflows, branching, and orchestration.pipe(...) plus combinators for short local transformations.Prefer:
Effect.map((user) => formatUser(user))
Over:
Effect.map(formatUser)
This follows the official guidance to avoid tacit usage because it can hurt inference, overload resolution, and stack traces.
Good defaults:
Effect.fail(...) for expected failuresEffect.try(...) / Effect.tryPromise(...) when wrapping throwing or rejecting APIscatchTag, catchAll, and mapError for recovery and translationAvoid:
Effect.syncOption.none() when the caller needs an explanationunknown or Error too earlyContext.Tag.Layer for reusable dependency graphs.Prefer:
Do not manually thread giant dependency objects through business logic if Effect requirements can model them cleanly.
Effect.acquireRelease, Effect.addFinalizer, and scoped layers over manual cleanup bookkeeping.If something must always be cleaned up, model it in the effect structure rather than relying on convention.
NodeRuntime.runMain(...) for the main program so shutdown is graceful.Effect.runPromise or Effect.runSync inside library code, helpers, or domain modules.Effect.all(...) and concurrency options for independent work.Schema at boundaries for parsing, validation, and encoding.Option, Either, Data, Chunk, Duration, and other Effect data types when they make semantics clearer.null and undefined in domain modeling when Option or a tagged union is better.Effect.tryPromise unless rejection is impossible.When writing or reviewing Effect code, check:
Effect.gen or pipelines in a way that is easy to follow?