<A, D, E>(
iterable: AsyncIterable<A, D>,
onError: (error: unknown) => E
): Channel<A, E, D>Creates a channel that pulls values from an AsyncIterable.
Details
Each yielded value is emitted as an output element. The iterator's return
value becomes the channel's done value. Thrown or rejected iterator errors
are converted with onError. If the channel scope closes early and the
iterator has a return method, that method is called.
export const const fromAsyncIterable: <A, D, E>(
iterable: AsyncIterable<A, D>,
onError: (error: unknown) => E
) => Channel<A, E, D>
Creates a channel that pulls values from an AsyncIterable.
Details
Each yielded value is emitted as an output element. The iterator's return
value becomes the channel's done value. Thrown or rejected iterator errors
are converted with onError. If the channel scope closes early and the
iterator has a return method, that method is called.
fromAsyncIterable = <function (type parameter) A in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>A, function (type parameter) D in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>D, function (type parameter) E in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>E>(
iterable: AsyncIterable<A, D>iterable: interface AsyncIterable<T, TReturn = any, TNext = any>AsyncIterable<function (type parameter) A in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>A, function (type parameter) D in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>D>,
onError: (error: unknown) => EonError: (error: unknownerror: unknown) => function (type parameter) E in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>E
): interface Channel<out OutElem, out OutErr = never, out OutDone = void, in InElem = unknown, in InErr = unknown, in InDone = unknown, out Env = never>A Channel is a nexus of I/O operations, which supports both reading and
writing. A channel may read values of type InElem and write values of type
OutElem. When the channel finishes, it yields a value of type OutDone. A
channel may fail with a value of type OutErr.
Details
Channels are the foundation of Streams: both streams and sinks are built on
channels. Most users shouldn't have to use channels directly, as streams and
sinks are much more convenient and cover all common use cases. However, when
adding new stream and sink operators, or doing something highly specialized,
it may be useful to use channels directly.
Channels compose in a variety of ways:
- Piping: One channel can be piped to another channel, assuming the
input type of the second is the same as the output type of the first.
- Sequencing: The terminal value of one channel can be used to create
another channel, and both the first channel and the function that makes
the second channel can be composed into a channel.
- Concatenating: The output of one channel can be used to create other
channels, which are all concatenated together. The first channel and the
function that makes the other channels can be composed into a channel.
Example (Typing channels)
import type { Channel } from "effect"
// A channel that outputs numbers and requires no environment
type NumberChannel = Channel.Channel<number>
// A channel that outputs strings, can fail with Error, completes with boolean
type StringChannel = Channel.Channel<string, Error, boolean>
// A channel with all type parameters specified
type FullChannel = Channel.Channel<
string, // OutElem - output elements
Error, // OutErr - output errors
number, // OutDone - completion value
number, // InElem - input elements
string, // InErr - input errors
boolean, // InDone - input completion
{ db: string } // Env - required environment
>
Channel<function (type parameter) A in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>A, function (type parameter) E in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>E, function (type parameter) D in <A, D, E>(iterable: AsyncIterable<A, D>, onError: (error: unknown) => E): Channel<A, E, D>D> =>
const fromTransform: <
OutElem,
OutErr,
OutDone,
InElem,
InErr,
InDone,
EX,
EnvX,
Env
>(
transform: (
upstream: Pull.Pull<InElem, InErr, InDone>,
scope: Scope.Scope
) => Effect.Effect<
Pull.Pull<OutElem, OutErr, OutDone, EnvX>,
EX,
Env
>
) => Channel<
OutElem,
Pull.ExcludeDone<OutErr> | EX,
OutDone,
InElem,
InErr,
InDone,
Env | EnvX
>
Creates a Channel from a transformation function that operates on upstream pulls.
Example (Creating channels from transforms)
import { Channel, Effect } from "effect"
const channel = Channel.fromTransform((upstream, scope) =>
Effect.succeed(upstream)
)
fromTransform(import EffectEffect.const fnUntraced: <Effect.Effect<void, never, never>, Effect.Effect<A, any, never>, [_: Pull.Pull<unknown, unknown, unknown, never>, scope: Scope.Scope]>(body: (this: Types.unassigned, _: Pull.Pull<unknown, unknown, unknown, never>, scope: Scope.Scope) => Generator<Effect.Effect<void, never, never>, Effect.Effect<A, any, never>, never>) => (_: Pull.Pull<unknown, unknown, unknown, never>, scope: Scope.Scope) => Effect.Effect<Effect.Effect<A, any, never>, never, never> (+41 overloads)fnUntraced(function*(_: Pull.Pull<
unknown,
unknown,
unknown,
never
>
(parameter) _: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
_, scope: Scope.Scope(parameter) scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope) {
const const iter: AsyncIterator<A, D, any>iter = iterable: AsyncIterable<A, D>iterable[var Symbol: SymbolConstructorSymbol.SymbolConstructor.asyncIterator: typeof Symbol.asyncIteratorA method that returns the default async iterator for an object. Called by the semantics of
the for-await-of statement.
asyncIterator]()
if (const iter: AsyncIterator<A, D, any>iter.AsyncIterator<A, D, any>.return?(value?: D | PromiseLike<D> | undefined): Promise<IteratorResult<A, D>>return) {
yield* import ScopeScope.const addFinalizer: (
scope: Scope,
finalizer: Effect<unknown>
) => Effect<void>
Registers a finalizer effect on a scope.
Details
If the scope is open, the finalizer runs when the scope closes, regardless of
whether the scope closes successfully or with an error. If the scope is
already closed, the finalizer runs immediately.
Example (Adding finalizers)
import { Console, Effect, Exit, Scope } from "effect"
const program = Effect.gen(function*() {
const scope = yield* Scope.make()
// Add simple finalizers
yield* Scope.addFinalizer(scope, Console.log("Cleanup task 1"))
yield* Scope.addFinalizer(scope, Console.log("Cleanup task 2"))
yield* Scope.addFinalizer(scope, Effect.log("Cleanup task 3"))
// Do some work
yield* Console.log("Doing work...")
// Close the scope
yield* Scope.close(scope, Exit.void)
})
addFinalizer(scope: Scope.Scope(parameter) scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope, import EffectEffect.const promise: <A>(
evaluate: (
signal: AbortSignal
) => PromiseLike<A>
) => Effect<A>
Creates an Effect that represents an asynchronous computation guaranteed to
succeed.
When to use
Use to convert a Promise into an Effect when the async operation is
guaranteed to succeed and will not reject.
Details
An optional AbortSignal can be provided to allow for interruption of the
wrapped Promise API.
Gotchas
The Promise must not reject. If it rejects, the rejection is treated as a
defect, not as a typed failure. Use tryPromise when rejection is expected.
Interruption aborts the provided AbortSignal, but the underlying
asynchronous operation only stops if it observes that signal.
Example (Wrapping a non-rejecting Promise)
import { Effect } from "effect"
const delay = (message: string) =>
Effect.promise<string>(
() =>
new Promise((resolve) => {
setTimeout(() => {
resolve(message)
}, 2000)
})
)
// ┌─── Effect<string, never, never>
// ▼
const program = delay("Async operation completed successfully!")
promise(() => const iter: AsyncIterator<A, D, any>iter.AsyncIterator<A, D, any>.return?(value?: D | PromiseLike<D> | undefined): Promise<IteratorResult<A, D>>return!()))
}
return import EffectEffect.const flatMap: {
<A, B, E1, R1>(
f: (a: A) => Effect<B, E1, R1>
): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E1 | E, R1 | R>
<A, E, R, B, E1, R1>(
self: Effect<A, E, R>,
f: (a: A) => Effect<B, E1, R1>
): Effect<B, E | E1, R | R1>
}
flatMap(
import EffectEffect.const tryPromise: <
A,
E = Cause.UnknownError
>(
options:
| {
readonly try: (
signal: AbortSignal
) => PromiseLike<A>
readonly catch: (error: unknown) => E
}
| ((signal: AbortSignal) => PromiseLike<A>)
) => Effect<A, E>
Creates an Effect from an asynchronous computation that may throw or
reject, mapping failures into the error channel.
When to use
Use when you need to perform asynchronous operations that might fail, such
as fetching data from an API, and want thrown exceptions or rejected promises
captured as Effect errors.
Details
The promise thunk is evaluated when the effect runs. If it returns a promise
that resolves, the resolved value becomes the success value. If the thunk
throws before returning a promise, or if the returned promise rejects, the
thrown or rejected value is mapped into the error channel.
Passing the thunk directly maps failures to
Cause.UnknownError
.
Passing { try, catch } uses catch to map failures to an error of type
E.
The thunk receives an AbortSignal that is aborted if the effect is
interrupted. The underlying asynchronous operation only stops if it observes
that signal.
Gotchas
If catch throws while mapping the error, that thrown value is treated as a
defect. Return the error value you want in the error channel instead of
throwing it.
Example (Wrapping a fetch request that may fail)
import { Effect } from "effect"
const getTodo = (id: number) =>
// Will catch any errors and propagate them as UnknownError
Effect.tryPromise(() =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
)
// ┌─── Effect<Response, UnknownError, never>
// ▼
const program = getTodo(1)
Example (Mapping Promise rejections to a tagged error)
import { Data, Effect } from "effect"
class TodoFetchError extends Data.TaggedError("TodoFetchError")<{ readonly cause: unknown }> {}
const getTodo = (id: number) =>
Effect.tryPromise({
try: () => fetch(`https://jsonplaceholder.typicode.com/todos/${id}`),
// remap the error
catch: (cause) => new TodoFetchError({ cause })
})
// ┌─── Effect<Response, TodoFetchError, never>
// ▼
const program = getTodo(1)
tryPromise({
try: (
signal: AbortSignal
) => PromiseLike<IteratorResult<A, D>>
try: () => const iter: AsyncIterator<A, D, any>iter.AsyncIterator<A, D, any>.next(...[value]: [] | [any]): Promise<IteratorResult<A, D>>next(),
catch: (error: unknown) => Ecatch: onError: (error: unknown) => EonError
}),
(result: IteratorResult<A, D>result) => result: IteratorResult<A, D>result.done?: boolean | undefineddone ? import CauseCause.done(result: IteratorReturnResult<D>result.IteratorReturnResult<D>.value: Dvalue) : import EffectEffect.const succeed: <A>(value: A) => Effect<A>Creates an Effect that always succeeds with a given value.
When to use
Use when an effect should complete successfully with a specific value without any errors
or external dependencies.
Example (Creating a successful effect)
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)
succeed(result: IteratorYieldResult<A>result.IteratorYieldResult<A>.value: Avalue)
)
}))