Utils
Internal and advanced utilities used by Effect's generator-based syntax and higher-kinded type support. This is not a general-purpose utility module for application code.
SingleShotGen makes an Effect-style value work with yield* inside
generator helpers. Variance and Gen provide the type-level signatures
used by modules such as Effect, Option, and Result to type their
gen APIs.
Constructors
SingleShotGen
Yields its wrapped value exactly once through an IterableIterator.
When to use
Use to implement [Symbol.iterator]() on Effect-like types so they can be
yield*-ed inside generator functions, such as Effect.gen and
Option.gen.
Details
The first call to next() returns { value: self, done: false }. Every
subsequent call returns { value: a, done: true } where a is the argument
passed to next(). [Symbol.iterator]() returns a new SingleShotGen
wrapping the same value, so the outer type can be iterated multiple times.
See
- Gen for the type-level signature that relies on
SingleShotGen
Signature
declare class SingleShotGen<T, A> implements IterableIterator<T, A> { constructor<T, A>(self: T); readonly self: T; [iterator](): IterableIterator<T, A>; next(a: A): IteratorResult<T, A>;}Example
(Yielding a wrapped value in a generator)
import { Utils } from "effect"
const gen = new Utils.SingleShotGen<string, number>("hello")
gen.next(0) // => { value: "hello", done: false }
gen.next(42) // => { value: 42, done: true }Models
Type-level signature for generator-based monadic composition over any
TypeLambda.
When to use
Use to type the gen function of a module that supports generator syntax,
such as Option.gen, Result.gen, and Effect.gen.
Details
This is a pure type alias with no runtime behavior. It infers R, O, and
E from the yielded values via Variance or Kind constraints. The
generator's return type A becomes the output's A parameter.
See
- Variance for encoding the variance used for inference
- SingleShotGen for the iterator protocol that makes yielding work
Signature
type Gen<F extends TypeLambda> = <Self, K extends Variance<F, any, any, any> | Kind<F, any, any, any, any>, A>(...args: [self: Self, body: (this: Self) => Generator<K, A, never>] | [body: () => Generator<K, A, never>]) => Kind<F, [K] extends [Variance<F, infer R, any, any>] ? R : [K] extends [Kind<F, infer R, any, any, any>] ? R : never, [K] extends [Variance<F, any, infer O, any>] ? O : [K] extends [Kind<F, any, infer O, any, any>] ? O : never, [K] extends [Variance<F, any, any, infer E>] ? E : [K] extends [Kind<F, any, any, infer E, any>] ? E : never, A>Example
(Typing a gen function for Option)
import { Option } from "effect"import type { Utils } from "effect"
const gen: Utils.Gen<Option.OptionTypeLambda> = Option.genconst result = gen(function*() { return yield* Option.some(1)})result // => Option.some(1)Type-level marker encoding the variance of a TypeLambda's type
parameters.
When to use
Use to define variance constraints for a higher-kinded type so that
Gen can correctly infer R, O, and E from yielded values.
Details
F is invariant and must match exactly. R is contravariant in the input
or environment position. O and E are covariant in the output and error
positions. This is a pure type-level construct with no runtime
representation.
See
- Gen for the type-level signature that uses
Variance
Signature
interface Variance<in out F extends TypeLambda, in R, out O, out E> { readonly _E: Covariant<E>; readonly _F: Invariant<F>; readonly _O: Covariant<O>; readonly _R: Contravariant<R>;}Example
(Declaring variance for a TypeLambda)
import type { Option, Utils } from "effect"
const variance: Utils.Variance< Option.OptionTypeLambda, unknown, string, string> = { _F: (value) => value, _R: () => {}, _O: () => "output", _E: () => "error"}Array.of(variance._O(undefined as never), variance._E(undefined as never)) // => ["output", "error"]