Skip to content
Effect Days 2026 Get your ticket

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.

3 exports Added in v2.0.0 Source

Constructors

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

Gen type

Added in v2.0.0 Source

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.gen
const result = gen(function*() {
return yield* Option.some(1)
})
result // => Option.some(1)

Variance interface

Added in v2.0.0 Source

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"]