(node: AnyNode, payload: { readonly token: string }): Effect.Effect<
void,
| AssumeTokenMismatch
| AssumeTokenReused
| AssumeNotReady
| NodeUnreachable
| UnaddressedNode
>Call NodeStatusTag.assume on node with { token } — Track A ownership ack.
export const const assume: (
node: AnyNode,
payload: { readonly token: string }
) => Effect.Effect<
void,
| AssumeTokenMismatch
| AssumeTokenReused
| AssumeNotReady
| NodeUnreachable
| UnaddressedNode
>
Call
NodeStatusTag
.assume on node with { token } — Track A ownership ack.
assume = (
node: AnyNodenode: type AnyNode = NodeKey<unknown> & {
readonly url: string | undefined;
readonly path: string | undefined;
readonly kind: ProtocolKind | undefined;
readonly endpoints?: Endpoints;
readonly onConflict?: OnConflict;
readonly [portSym]?: number;
}
A
Tag
erased — its transport endpoints set, plus the primary address
(url and/or Unix path) and
ProtocolKind
kind (the first-declared endpoint, kept for
single-protocol readers), so a tag's distributed set is self-describing about where AND how to
reach each one.
AnyNode,
payload: {
readonly token: string
}
payload: { readonly token: stringtoken: string },
): import EffectEffect.interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<
void,
| class AssumeTokenMismatchclass AssumeTokenMismatch {
message: string;
_tag: 'AssumeTokenMismatch';
node: string;
name: string;
stack: string;
cause: unknown;
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;
}
Node.assume was called with a token that does not match the node's expected token
(or the node has no assume token configured).
AssumeTokenMismatch
| class AssumeTokenReusedclass AssumeTokenReused {
message: string;
_tag: 'AssumeTokenReused';
node: string;
name: string;
stack: string;
cause: unknown;
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;
}
Node.assume succeeded once already — tokens are single-use for Track A handoff.
AssumeTokenReused
| class AssumeNotReadyclass AssumeNotReady {
message: string;
node: string;
_tag: 'AssumeNotReady';
serviceKey: string | undefined;
detail: string | undefined;
name: string;
stack: string;
cause: unknown;
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;
}
Node.assume rejected because the node is not Ready yet (served HyperServices not all
ready, or a configured subset is not ready). Ready ≠ ownership — wait for Ready, then assume.
AssumeNotReady
| class NodeUnreachableclass NodeUnreachable {
message: string;
name: string;
stack: string;
cause: unknown;
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;
_tag: Tag;
node: string;
url: string;
}
A remote
Node
that didn't answer at its declared address — down, wrong port/url, or (for a
socket node) a server not speaking the socket protocol. Surfaced eagerly by
verifyConnection
so a client fails fast at startup instead of hanging or erroring opaquely at the first call.
NodeUnreachable
| class UnaddressedNodeclass UnaddressedNode {
message: string;
name: string;
stack: string;
cause: unknown;
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;
_tag: Tag;
node: string;
}
Deriving a transport from a node that never declared one — a bare Node.Tag()("x") has no
address/kind, so connect / listen can't know how to reach it. Surfaces on the Layer / Effect
error channel (never a sync throw).
UnaddressedNode
> => {
if (!function isAddressedNode(node: AnyNode): node is AddressedNode<unknown>Runtime predicate: node declares a
ProtocolKind
and the matching address
(path for IpcSocket, url otherwise) so
connect
can derive a transport.
isAddressedNode(node: AnyNodenode)) {
return import EffectEffect.const fail: <E>(
error: E
) => Effect<never, E>
Creates an Effect that represents a recoverable error.
When to use
Use to explicitly signal a recoverable error in an Effect.
Details
The error keeps propagating unless it is handled. You can handle tagged
errors with functions like
catchTag
or
catchTags
.
Example (Creating a failed effect)
import { Data, Effect } from "effect"
class OperationFailedError extends Data.TaggedError("OperationFailedError")<{}> {}
// ┌─── Effect<never, OperationFailedError, never>
// ▼
const failure = Effect.fail(
new OperationFailedError()
)
fail(new new UnaddressedNode<{
readonly node: string;
}>(args: {
readonly node: string;
}): UnaddressedNode
Deriving a transport from a node that never declared one — a bare Node.Tag()("x") has no
address/kind, so connect / listen can't know how to reach it. Surfaces on the Layer / Effect
error channel (never a sync throw).
UnaddressedNode({ node: stringnode: node: AnyNodenode.Key<unknown, NodeProtocol>.key: stringkey }));
}
const const address: stringaddress =
typeof node: AnyNodenode.url: string | undefinedurl === "string"
? node: AnyNodenode.url: stringurl
: typeof node: AnyNodenode.path: string | undefinedpath === "string"
? node: AnyNodenode.path: stringpath
: node: AnyNodenode.Key<out Identifier, out Shape>.key: stringkey;
return import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
gen(function* () {
yield* import EffectEffect.const logDebug: (
...message: ReadonlyArray<any>
) => Effect<void>
Logs one or more messages at the DEBUG level.
Example (Logging debug messages)
import { Effect } from "effect"
const program = Effect.gen(function*() {
yield* Effect.logDebug("Debug mode enabled")
const userInput = { name: "Alice", age: 30 }
yield* Effect.logDebug("Processing user input:", userInput)
// Useful for detailed diagnostic information
yield* Effect.logDebug("Variable state:", "x=10", "y=20", "z=30")
})
Effect.runPromise(program)
// Output:
// timestamp=2023-... level=DEBUG message="Debug mode enabled"
// timestamp=2023-... level=DEBUG message="Processing user input: [object Object]"
// timestamp=2023-... level=DEBUG message="Variable state: x=10 y=20 z=30"
logDebug("Node.assume dialing peer").Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+21 overloads)pipe(
import EffectEffect.const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)annotateLogs({
"assume.node": node: AnyNodenode.Key<out Identifier, out Shape>.key: stringkey,
"assume.address": const address: stringaddress,
}),
);
const { const NodeStatusTag: typeof NodeStatusTagconst NodeStatusTag: {
key: Identifier;
Service: {
status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly contractHash?: string | un…;
ping: Effect.Effect<number, never, never>;
yield: Effect.Effect<boolean, never, never>;
assume: (payload: { token: string }) => Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, never>;
logs: { readonly stream: Stream<{ readonly annotations: { readonly [x: string]: string }; readonly spans: ReadonlyArray<string>; readonly date: string; readonly level: 'None' | 'All' | 'Fatal' | 'Error' | 'Warn' | 'Info' | 'Debug' | 'Trace'; rea…;
};
description: string | undefined;
of: (this: void, self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefine…;
context: (self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly …;
use: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
useSync: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
Identifier: Identifier;
stack: string | undefined;
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;
}
The reserved node status HyperService tag — nodeless, so a client queries it over whichever node
transport it points the ambient RpcClient.Protocol at.
NodeStatusTag } = yield* 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(() => import("./nodeStatus"));
const const ctx: Context<NodeStatusTag>const ctx: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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;
}
ctx = yield* import LayerLayer.const build: <RIn, E, ROut>(
self: Layer<ROut, E, RIn>
) => Effect<
Context.Context<ROut>,
E,
RIn | Scope.Scope
>
Builds a layer into a scoped value.
Example (Building a layer into a context)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
// Build a layer to get its services
const program = Effect.gen(function*() {
const dbLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed("result"))
})
// Build the layer into Context - automatically manages scope and memoization
const context = yield* Layer.build(dbLayer)
// Extract the specific service from the built layer
const database = Context.get(context, Database)
return yield* database.query("SELECT * FROM users")
})
build(
import HyperlinkHyperlink.client<NodeStatusTag, {
readonly status: Hyperlink.Marked<Hyperlink.Method<undefined, Schema.Struct<{
readonly up: Schema.Boolean;
readonly status: Schema.Literals<readonly ["ok", "degraded"]>;
readonly startedAt: Schema.DateTimeUtc;
readonly uptimeMillis: Schema.Number;
readonly serviceCount: Schema.Number;
readonly services: Schema.$Array<Schema.Struct<{
readonly key: Schema.String;
readonly kind: Schema.String;
readonly ready: Schema.Boolean;
readonly detail: Schema.optionalKey<Schema.String>;
readonly contractHash: Schema.optionalKey<Schema.String>;
}>>;
readonly ownership: Schema.optionalKey<...>;
}>, Schema.Never, true, Hyperlink.MethodAnnotations & {
...;
}, Hyperlink.Derive>, {
...;
}>;
readonly ping: Hyperlink.Method<...>;
readonly yield: Hyperlink.Method<...>;
readonly assume: Hyperlink.Method<...>;
readonly logs: {
...;
};
}, unknown>(tag: Hyperlink.HyperlinkTag<...>, node: AddressedNode<...>): Layer.Layer<...> (+4 overloads)
export client
The client layer for a serviceKey: drive it over RPC as if it were local — the exact
same yield* Tag code as the local layer, only the provided layer differs, so it doesn't
matter where the HyperService actually runs.
Paths, by whether — and where — the tag names a
Node
:
- **node-bearing +
AddressedNode
** —
client(Hosted) when the tag's { node } is
dialable: auto-wires connect (R = never). Bare bound nodes still require the node service.
- **nodeless tag +
AddressedNode
** —
client(tag, Worker) same auto-connect gate.
- bare node —
client(tag, Bare) / bare-bound client(Hosted) still require the node;
provide
Node.connect
(Bare, protocol) (or lookup /
unix
(tag)) yourself.
- nodeless tag, ambient transport — ambient
RpcClient.Protocol.
client(const NodeStatusTag: typeof NodeStatusTagconst NodeStatusTag: {
key: Identifier;
Service: {
status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly contractHash?: string | un…;
ping: Effect.Effect<number, never, never>;
yield: Effect.Effect<boolean, never, never>;
assume: (payload: { token: string }) => Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, never>;
logs: { readonly stream: Stream<{ readonly annotations: { readonly [x: string]: string }; readonly spans: ReadonlyArray<string>; readonly date: string; readonly level: 'None' | 'All' | 'Fatal' | 'Error' | 'Warn' | 'Info' | 'Debug' | 'Trace'; rea…;
};
description: string | undefined;
of: (this: void, self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefine…;
context: (self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly …;
use: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
useSync: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
Identifier: Identifier;
stack: string | undefined;
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;
}
The reserved node status HyperService tag — nodeless, so a client queries it over whichever node
transport it points the ambient RpcClient.Protocol at.
NodeStatusTag, node: AnyNodenode).Pipeable.pipe<Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never>, Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never>>(this: Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never>, ab: (_: Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never>) => Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never>): Layer.Layer<NodeStatusTag, Hyperlink.ClientVerifyError, never> (+21 overloads)pipe(
import LayerLayer.const provide: {
<RIn, E, ROut>(that: Layer<ROut, E, RIn>): <
RIn2,
E2,
ROut2
>(
self: Layer<ROut2, E2, RIn2>
) => Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<Layers extends [Any, ...Array<Any>]>(
that: Layers
): <A, E, R>(
self: Layer<A, E, R>
) => Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
<RIn2, E2, ROut2, RIn, E, ROut>(
self: Layer<ROut2, E2, RIn2>,
that: Layer<ROut, E, RIn>
): Layer<
ROut2,
E | E2,
RIn | Exclude<RIn2, ROut>
>
<A, E, R, Layers extends [Any, ...Array<Any>]>(
self: Layer<A, E, R>,
that: Layers
): Layer<
A,
E | Error<Layers[number]>,
| Services<Layers[number]>
| Exclude<R, Success<Layers[number]>>
>
}
Feeds the output services of the dependency layer into the requirements of
this layer, returning a layer that only provides the services from this layer.
When to use
Use when you need to hide an implementation dependency layer from callers.
Details
In serviceLayer.pipe(Layer.provide(dependencyLayer)), the dependency layer is
built first and is used to satisfy the requirements of serviceLayer.
Example (Providing layer dependencies)
import { Context, Effect, Layer } from "effect"
class Database extends Context.Service<Database, {
readonly query: (sql: string) => Effect.Effect<string>
}>()("Database") {}
class UserService extends Context.Service<UserService, {
readonly getUser: (id: string) => Effect.Effect<{
id: string
name: string
}>
}>()("UserService") {}
class Logger extends Context.Service<Logger, {
readonly log: (msg: string) => Effect.Effect<void>
}>()("Logger") {}
// Create dependency layers
const databaseLayer = Layer.succeed(Database, {
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`DB: ${sql}`))
})
const loggerLayer = Layer.succeed(Logger, {
log: Effect.fn("Logger.log")((msg: string) => Effect.sync(() => console.log(`[LOG] ${msg}`)))
})
// UserService depends on Database and Logger
const userServiceLayer = Layer.effect(UserService, Effect.gen(function*() {
const database = yield* Database
const logger = yield* Logger
return {
getUser: Effect.fn("UserService.getUser")(function*(id: string) {
yield* logger.log(`Looking up user ${id}`)
const result = yield* database.query(
`SELECT * FROM users WHERE id = ${id}`
)
return { id, name: result }
})
}
}))
// Provide dependencies to UserService layer
const userServiceWithDependencies = userServiceLayer.pipe(
Layer.provide(Layer.mergeAll(databaseLayer, loggerLayer))
)
// Now UserService layer has no dependencies
const program = Effect.gen(function*() {
const userService = yield* UserService
return yield* userService.getUser("123")
}).pipe(
Effect.provide(userServiceWithDependencies)
)
provide(import HyperlinkHyperlink.const clientVerify: (
mode: ClientVerifyMode
) => Layer.Layer<never>
Override
ClientVerify
for addressed client layers.
clientVerify(false)),
),
);
yield* import EffectEffect.const gen: {
<Eff extends Effect<any, any, any>, AEff>(
f: () => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
<Self, Eff extends Effect<any, any, any>, AEff>(
options: { readonly self: Self },
f: (this: Self) => Generator<Eff, AEff, never>
): Effect<
AEff,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer E, infer _R>
]
? E
: never,
[Eff] extends [never]
? never
: [Eff] extends [
Effect<infer _A, infer _E, infer R>
]
? R
: never
>
}
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to use
Use when you want to write effectful code that looks and behaves like
synchronous code, while still handling asynchronous tasks, errors, and complex
control flow such as loops and conditions.
Generator functions work similarly to async/await but keep errors,
requirements, and interruption in the Effect type. You can yield* values
from effects and return the final result at the end.
Example (Sequencing effects with generators)
import { Data, Effect } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function*() {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})
gen(function* () {
const const status: {
readonly status: Hyperlink.Subscribable<{
readonly status: "ok" | "degraded";
readonly services: readonly {
readonly kind: string;
readonly key: string;
readonly ready: boolean;
readonly detail?: string | undefined;
readonly contractHash?: string | undefined;
}[];
readonly up: boolean;
readonly startedAt: Utc;
readonly uptimeMillis: number;
readonly serviceCount: number;
readonly ownership?: "launcher" | "self" | undefined;
}>;
readonly ping: Effect.Effect<number, never, never>;
readonly yield: Effect.Effect<boolean, never, never>;
readonly assume: (payload: {
...;
}) => Effect.Effect<...>;
readonly logs: {
...;
};
}
status = yield* const NodeStatusTag: typeof NodeStatusTagconst NodeStatusTag: {
key: Identifier;
Service: {
status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly contractHash?: string | un…;
ping: Effect.Effect<number, never, never>;
yield: Effect.Effect<boolean, never, never>;
assume: (payload: { token: string }) => Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, never>;
logs: { readonly stream: Stream<{ readonly annotations: { readonly [x: string]: string }; readonly spans: ReadonlyArray<string>; readonly date: string; readonly level: 'None' | 'All' | 'Fatal' | 'Error' | 'Warn' | 'Info' | 'Debug' | 'Trace'; rea…;
};
description: string | undefined;
of: (this: void, self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefine…;
context: (self: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; readonly …;
use: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
useSync: (f: (service: { readonly status: Hyperlink.Subscribable<{ readonly status: 'ok' | 'degraded'; readonly services: ReadonlyArray<{ readonly kind: string; readonly key: string; readonly ready: boolean; readonly detail?: string | undefined; re…;
Identifier: Identifier;
stack: string | undefined;
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;
}
The reserved node status HyperService tag — nodeless, so a client queries it over whichever node
transport it points the ambient RpcClient.Protocol at.
NodeStatusTag;
return yield* const status: {
readonly status: Hyperlink.Subscribable<{
readonly status: "ok" | "degraded";
readonly services: readonly {
readonly kind: string;
readonly key: string;
readonly ready: boolean;
readonly detail?: string | undefined;
readonly contractHash?: string | undefined;
}[];
readonly up: boolean;
readonly startedAt: Utc;
readonly uptimeMillis: number;
readonly serviceCount: number;
readonly ownership?: "launcher" | "self" | undefined;
}>;
readonly ping: Effect.Effect<number, never, never>;
readonly yield: Effect.Effect<boolean, never, never>;
readonly assume: (payload: {
...;
}) => Effect.Effect<...>;
readonly logs: {
...;
};
}
status.assume: (payload: {
token: string
}) => Effect.Effect<
void,
| AssumeTokenMismatch
| AssumeTokenReused
| AssumeNotReady,
never
>
Launcher → node ownership ack — child assumes self-custody so the launcher may exit.
Rejects until Ready; token is single-use; mismatch / reuse / not-ready are loud tagged errors.
assume(payload: {
readonly token: string
}
payload);
}).Pipeable.pipe<Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, NodeStatusTag>, Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, never>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady, NodeStatusTag>) => Effect.Effect<void, AssumeTokenMismatch | ... 1 more ... | AssumeNotReady, never>): Effect.Effect<...> (+21 overloads)pipe(import EffectEffect.const provide: {
<
Layers extends [
Layer.Any,
...Array<Layer.Any>
]
>(
layers: Layers,
options?:
| { readonly local?: boolean | undefined }
| undefined
): <A, E, R>(
self: Effect<A, E, R>
) => Effect<
A,
E | Layer.Error<Layers[number]>,
| Layer.Services<Layers[number]>
| Exclude<R, Layer.Success<Layers[number]>>
>
<ROut, E2, RIn>(
layer: Layer.Layer<ROut, E2, RIn>,
options?:
| { readonly local?: boolean | undefined }
| undefined
): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E | E2, RIn | Exclude<R, ROut>>
<R2>(context: Context.Context<R2>): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, Exclude<R, R2>>
<
A,
E,
R,
Layers extends [
Layer.Any,
...Array<Layer.Any>
]
>(
self: Effect<A, E, R>,
layers: Layers,
options?:
| { readonly local?: boolean | undefined }
| undefined
): Effect<
A,
E | Layer.Error<Layers[number]>,
| Layer.Services<Layers[number]>
| Exclude<R, Layer.Success<Layers[number]>>
>
<A, E, R, ROut, E2, RIn>(
self: Effect<A, E, R>,
layer: Layer.Layer<ROut, E2, RIn>,
options?:
| { readonly local?: boolean | undefined }
| undefined
): Effect<A, E | E2, RIn | Exclude<R, ROut>>
<A, E, R, R2>(
self: Effect<A, E, R>,
context: Context.Context<R2>
): Effect<A, E, Exclude<R, R2>>
}
Provides dependencies to an effect using layers or a context. Use options.local
to build the layer every time; by default, layers are shared between provide
calls.
Example (Providing dependencies with a layer)
import { Context, Effect, Layer } from "effect"
interface Database {
readonly query: (sql: string) => Effect.Effect<string>
}
const Database = Context.Service<Database>("Database")
const DatabaseLive = Layer.succeed(Database)({
query: Effect.fn("Database.query")((sql: string) => Effect.succeed(`Result for: ${sql}`))
})
const program = Effect.gen(function*() {
const db = yield* Database
return yield* db.query("SELECT * FROM users")
})
const provided = Effect.provide(program, DatabaseLive)
Effect.runPromise(provided).then(console.log)
// Output: "Result for: SELECT * FROM users"
provide(const ctx: Context<NodeStatusTag>const ctx: {
mapUnsafe: ReadonlyMap<string, any>;
mutable: boolean;
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;
}
ctx));
yield* import EffectEffect.const logInfo: (
...message: ReadonlyArray<any>
) => Effect<void>
Logs one or more messages at the INFO level.
Example (Logging information)
import { Effect } from "effect"
const program = Effect.gen(function*() {
yield* Effect.logInfo("Application starting up")
yield* Effect.logInfo("Config loaded:", "production", "Port:", 3000)
// Useful for general information
const version = "1.2.3"
yield* Effect.logInfo("Application version:", version)
})
Effect.runPromise(program)
// Output:
// timestamp=2023-... level=INFO message="Application starting up"
// timestamp=2023-... level=INFO message="Config loaded: production Port: 3000"
// timestamp=2023-... level=INFO message="Application version: 1.2.3"
logInfo("Node.assume acknowledged").Pipeable.pipe<Effect.Effect<void, never, never>, Effect.Effect<void, never, never>>(this: Effect.Effect<void, never, never>, ab: (_: Effect.Effect<void, never, never>) => Effect.Effect<void, never, never>): Effect.Effect<void, never, never> (+21 overloads)pipe(
import EffectEffect.const annotateLogs: (values: Record<string, unknown>) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+3 overloads)annotateLogs({ "assume.node": node: AnyNodenode.Key<out Identifier, out Shape>.key: stringkey }),
);
}).Pipeable.pipe<Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady | Hyperlink.ClientVerifyError, Scope>, Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady | Hyperlink.ClientVerifyError, never>, Effect.Effect<void, AssumeTokenMismatch | AssumeTokenReused | AssumeNotReady | Hyperlink.ClientVerifyError, never>, Effect.Effect<...>, Effect.Effect<...>>(this: Effect.Effect<...>, ab: (_: Effect.Effect<...>) => Effect.Effect<...>, bc: (_: Effect.Effect<...>) => Effect.Effect<...>, cd: (_: Effect.Effect<...>) => Effect.Effect<...>, de: (_: Effect.Effect<...>) => Effect.Effect<...>): Effect.Effect<...> (+21 overloads)pipe(
import EffectEffect.const scoped: <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E, Exclude<R, Scope>>
Runs an effect with a scope that closes when the effect completes.
When to use
Use to acquire scoped resources for the duration of a single workflow.
Details
Finalizers for resources acquired inside the workflow run as soon as the
workflow completes, whether by success, failure, or interruption.
Example (Running a scoped acquisition)
import { Console, Effect } from "effect"
const resource = Effect.acquireRelease(
Console.log("Acquiring resource").pipe(Effect.as("resource")),
() => Console.log("Releasing resource")
)
const program = Effect.scoped(
Effect.gen(function*() {
const res = yield* resource
yield* Console.log(`Using ${res}`)
return res
})
)
Effect.runFork(program)
// Output: "Acquiring resource"
// Output: "Using resource"
// Output: "Releasing resource"
scoped,
import EffectEffect.const withLogSpan: (label: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)withLogSpan("node.assume"),
import EffectEffect.const withSpan: {
<Args extends ReadonlyArray<any>>(
name: string,
options?:
| SpanOptionsNoTrace
| ((
...args: NoInfer<Args>
) => SpanOptionsNoTrace)
| undefined,
traceOptions?: TraceOptions | undefined
): <A, E, R>(
self: Effect<A, E, R>,
...args: Args
) => Effect<A, E, Exclude<R, ParentSpan>>
<A, E, R>(
self: Effect<A, E, R>,
name: string,
options?: SpanOptions | undefined
): Effect<A, E, Exclude<R, ParentSpan>>
}
Wraps the effect with a child span for tracing.
Example (Wrapping an effect in a child span)
import { Effect } from "effect"
const task = Effect.gen(function*() {
yield* Effect.log("Executing task")
return "result"
})
const traced = Effect.withSpan(task, "my-task", {
attributes: { version: "1.0" }
})
withSpan("node.assume", {
SpanOptionsNoTrace.attributes?: Record<string, unknown> | undefined(property) SpanOptionsNoTrace.attributes?: {
assume.node: string;
}
attributes: { "assume.node": node: AnyNodenode.Key<out Identifier, out Shape>.key: stringkey },
}),
import EffectEffect.const mapError: {
<E, E2>(f: (e: E) => E2): <A, R>(
self: Effect<A, E, R>
) => Effect<A, E2, R>
<A, E, R, E2>(
self: Effect<A, E, R>,
f: (e: E) => E2
): Effect<A, E2, R>
}
Transforms the failure value of an effect without changing its success value.
When to use
Use to translate an Effect's typed failures while leaving successful values
unchanged.
Details
Only the failure channel is transformed. The success channel and requirements
are preserved.
Example (Transforming the error channel)
import { Data, Effect } from "effect"
class TaskError extends Data.TaggedError("TaskError")<{ readonly message: string }> {}
// ┌─── Effect<number, string, never>
// ▼
const simulatedTask = Effect.fail("Oh no!").pipe(Effect.as(1))
// ┌─── Effect<number, TaskError, never>
// ▼
const mapped = Effect.mapError(
simulatedTask,
(message) => new TaskError({ message })
)
mapError((cause: | AssumeTokenMismatch
| AssumeTokenReused
| AssumeNotReady
| Hyperlink.ClientVerifyError
cause) => {
if (import SchemaSchema.const is: <S extends Schema.Constraint>(
schema: S
) => <I>(input: I) => input is I & S["Type"]
Creates a type guard that checks whether an input satisfies the schema's decoded
type side.
When to use
Use to build a type guard for checking the decoded side of a schema without
exposing issue details.
Details
The guard returns true on successful validation and false when validation
fails only with schema issues, without exposing issue details.
Gotchas
Only causes made entirely of schema issues are converted to false. Causes
that contain defects, interruptions, or asynchronous work at this synchronous
boundary throw an Error whose cause is the underlying Cause.
is(class AssumeTokenMismatchclass AssumeTokenMismatch {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: Schema.tag<'AssumeTokenMismatch'>; readonly node: Schema.String }) => To, options?: { readonly unsafePreserveChecks?: boolean | undefined } | undefined) => Schema.Struct<{ [K in keyof Readonly<To>]: Readonly<T…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Schema.Annotations.Declaration<Extended, readonly [Schema.Struct<{ [K in keyof { [K in keyof (('node' | '_tag') & keyof NewFields extends never ? { readonly _tag: Schema.tag<'Assu…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Schema.Annotations.Bottom<AssumeTokenMismatch, readonly [Schema.TaggedStruct<'AssumeTokenMismatch', { readonly node: Schema.String }>]>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenMismatch, Schema.Struct.Readonly…;
annotateKey: (annotations: Schema.Annotations.Key<AssumeTokenMismatch>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenMismatch, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenMismatch'>; readonly node: Schema.String }, 'En…;
check: (checks_0: Check<AssumeTokenMismatch>, ...checks: Array<Check<AssumeTokenMismatch>>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenMismatch, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenMismatch'>; readonly …;
rebuild: (ast: Declaration) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenMismatch, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenMismatch'>; readonly node: Schema.String }, 'Encoded'>, readonly [Schema.TaggedStruct<'…;
make: (input: { readonly node: string; readonly _tag?: 'AssumeTokenMismatch' | undefined }, options?: MakeOptions) => AssumeTokenMismatch;
makeOption: (input: { readonly node: string; readonly _tag?: 'AssumeTokenMismatch' | undefined }, options?: MakeOptions) => Option_.Option<AssumeTokenMismatch>;
makeEffect: (input: { readonly node: string; readonly _tag?: 'AssumeTokenMismatch' | undefined }, options?: MakeOptions) => Effect.Effect<AssumeTokenMismatch, SchemaError, never>;
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; <…;
}
Node.assume was called with a token that does not match the node's expected token
(or the node has no assume token configured).
AssumeTokenMismatch)(cause: | AssumeTokenMismatch
| AssumeTokenReused
| AssumeNotReady
| Hyperlink.ClientVerifyError
cause)) return cause: AssumeTokenMismatchcause;
if (import SchemaSchema.const is: <S extends Schema.Constraint>(
schema: S
) => <I>(input: I) => input is I & S["Type"]
Creates a type guard that checks whether an input satisfies the schema's decoded
type side.
When to use
Use to build a type guard for checking the decoded side of a schema without
exposing issue details.
Details
The guard returns true on successful validation and false when validation
fails only with schema issues, without exposing issue details.
Gotchas
Only causes made entirely of schema issues are converted to false. Causes
that contain defects, interruptions, or asynchronous work at this synchronous
boundary throw an Error whose cause is the underlying Cause.
is(class AssumeTokenReusedclass AssumeTokenReused {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: Schema.tag<'AssumeTokenReused'>; readonly node: Schema.String }) => To, options?: { readonly unsafePreserveChecks?: boolean | undefined } | undefined) => Schema.Struct<{ [K in keyof Readonly<To>]: Readonly<To>…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Schema.Annotations.Declaration<Extended, readonly [Schema.Struct<{ [K in keyof { [K in keyof (('node' | '_tag') & keyof NewFields extends never ? { readonly _tag: Schema.tag<'Assu…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Schema.Annotations.Bottom<AssumeTokenReused, readonly [Schema.TaggedStruct<'AssumeTokenReused', { readonly node: Schema.String }>]>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenReused, Schema.Struct.ReadonlySide<{…;
annotateKey: (annotations: Schema.Annotations.Key<AssumeTokenReused>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenReused, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenReused'>; readonly node: Schema.String }, 'Encoded'…;
check: (checks_0: Check<AssumeTokenReused>, ...checks: Array<Check<AssumeTokenReused>>) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenReused, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenReused'>; readonly node: Sc…;
rebuild: (ast: Declaration) => Schema.decodeTo<Schema.declareConstructor<AssumeTokenReused, Schema.Struct.ReadonlySide<{ readonly _tag: Schema.tag<'AssumeTokenReused'>; readonly node: Schema.String }, 'Encoded'>, readonly [Schema.TaggedStruct<'Assu…;
make: (input: { readonly node: string; readonly _tag?: 'AssumeTokenReused' | undefined }, options?: MakeOptions) => AssumeTokenReused;
makeOption: (input: { readonly node: string; readonly _tag?: 'AssumeTokenReused' | undefined }, options?: MakeOptions) => Option_.Option<AssumeTokenReused>;
makeEffect: (input: { readonly node: string; readonly _tag?: 'AssumeTokenReused' | undefined }, options?: MakeOptions) => Effect.Effect<AssumeTokenReused, SchemaError, never>;
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; <…;
}
Node.assume succeeded once already — tokens are single-use for Track A handoff.
AssumeTokenReused)(cause: | AssumeTokenReused
| AssumeNotReady
| Hyperlink.ClientVerifyError
cause)) return cause: AssumeTokenReusedcause;
if (import SchemaSchema.const is: <S extends Schema.Constraint>(
schema: S
) => <I>(input: I) => input is I & S["Type"]
Creates a type guard that checks whether an input satisfies the schema's decoded
type side.
When to use
Use to build a type guard for checking the decoded side of a schema without
exposing issue details.
Details
The guard returns true on successful validation and false when validation
fails only with schema issues, without exposing issue details.
Gotchas
Only causes made entirely of schema issues are converted to false. Causes
that contain defects, interruptions, or asynchronous work at this synchronous
boundary throw an Error whose cause is the underlying Cause.
is(class AssumeNotReadyclass AssumeNotReady {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: Schema.tag<'AssumeNotReady'>; readonly node: Schema.String; readonly serviceKey: Schema.optionalKey<Schema.String>; readonly detail: Schema.optionalKey<Schema.String> }) => To, options?: { readonly unsafePrese…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Schema.Annotations.Declaration<Extended, readonly [Schema.Struct<{ [K in keyof { [K in keyof (('node' | '_tag' | 'serviceKey' | 'detail') & keyof NewFields extends never ? { reado…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Schema.Annotations.Bottom<AssumeNotReady, readonly [Schema.TaggedStruct<'AssumeNotReady', { readonly node: Schema.String; readonly serviceKey: Schema.optionalKey<Schema.String>; readonly detail: Schema.optionalKey<Schema.Stri…;
annotateKey: (annotations: Schema.Annotations.Key<AssumeNotReady>) => Schema.decodeTo<Schema.declareConstructor<AssumeNotReady, { readonly node: string; readonly _tag: 'AssumeNotReady'; readonly serviceKey?: string | undefined; readonly detail?: string…;
check: (checks_0: Check<AssumeNotReady>, ...checks: Array<Check<AssumeNotReady>>) => Schema.decodeTo<Schema.declareConstructor<AssumeNotReady, { readonly node: string; readonly _tag: 'AssumeNotReady'; readonly serviceKey?: string | undefined; rea…;
rebuild: (ast: Declaration) => Schema.decodeTo<Schema.declareConstructor<AssumeNotReady, { readonly node: string; readonly _tag: 'AssumeNotReady'; readonly serviceKey?: string | undefined; readonly detail?: string | undefined }, readonly [Schema.Ta…;
make: (input: { readonly node: string; readonly _tag?: 'AssumeNotReady' | undefined; readonly serviceKey?: string | undefined; readonly detail?: string | undefined }, options?: MakeOptions) => AssumeNotReady;
makeOption: (input: { readonly node: string; readonly _tag?: 'AssumeNotReady' | undefined; readonly serviceKey?: string | undefined; readonly detail?: string | undefined }, options?: MakeOptions) => Option_.Option<AssumeNotReady>;
makeEffect: (input: { readonly node: string; readonly _tag?: 'AssumeNotReady' | undefined; readonly serviceKey?: string | undefined; readonly detail?: string | undefined }, options?: MakeOptions) => Effect.Effect<AssumeNotReady, SchemaError, never>;
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; <…;
}
Node.assume rejected because the node is not Ready yet (served HyperServices not all
ready, or a configured subset is not ready). Ready ≠ ownership — wait for Ready, then assume.
AssumeNotReady)(cause: | AssumeNotReady
| Hyperlink.ClientVerifyError
cause)) return cause: AssumeNotReadycause;
if (import PredicatePredicate.const isTagged: <"UnaddressedNode">(self: unknown, tag: "UnaddressedNode") => self is {
_tag: "UnaddressedNode";
} (+1 overload)
Checks whether a value has a _tag property equal to the given tag.
When to use
Use when you model tagged unions with a _tag field and want a quick
Predicate guard for tagged values.
Details
Uses hasProperty and strict equality on _tag.
Example (Guarding tagged values)
import { Predicate } from "effect"
const isOk = Predicate.isTagged("Ok")
console.log(isOk({ _tag: "Ok", value: 1 }))
isTagged(cause: Hyperlink.ClientVerifyErrorcause, "UnaddressedNode")) return cause: UnaddressedNode(parameter) cause: {
message: string;
name: string;
stack: string;
cause: unknown;
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;
_tag: Tag;
node: string;
}
cause;
return new new NodeUnreachable<{
readonly node: string;
readonly url: string;
readonly cause: unknown;
}>(args: {
readonly node: string;
readonly url: string;
readonly cause: unknown;
}): NodeUnreachable
A remote
Node
that didn't answer at its declared address — down, wrong port/url, or (for a
socket node) a server not speaking the socket protocol. Surfaced eagerly by
verifyConnection
so a client fails fast at startup instead of hanging or erroring opaquely at the first call.
NodeUnreachable({
node: stringnode: node: AnyNodenode.Key<out Identifier, out Shape>.key: stringkey,
url: stringurl: const address: stringaddress,
cause: unknowncause,
});
}),
);
};