(options: SqliteClientConfig): Effect.Effect<
SqliteClient,
never,
Scope.Scope | Reactivity.Reactivity
>Creates a scoped node SQLite client from the supplied configuration, using a single serialized connection with WAL enabled by default and exposing SQLite-specific export, backup, and loadExtension operations.
export const const make: (
options: SqliteClientConfig
) => Effect.Effect<
SqliteClient,
never,
Scope.Scope | Reactivity.Reactivity
>
Creates a scoped node SQLite client from the supplied configuration, using a single serialized connection with WAL enabled by default and exposing SQLite-specific export, backup, and loadExtension operations.
make = (
options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options: SqliteClientConfig
): 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<SqliteClient, never, import ScopeScope.Scope | import ReactivityReactivity.class Reactivityclass Reactivity {
key: Identifier;
Service: {
invalidateUnsafe: (keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>) => void;
registerUnsafe: (keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, handler: () => void) => () => void;
invalidate: (keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>) => Effect.Effect<void>;
mutation: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
query: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Effect.Effect<Queue.Dequeue<A, E>, never, R | Scope.Scope>;
stream: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Stream.Stream<A, E, Exclude<R, Scope.Scope>>;
withBatch: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
};
}
Service for key-based reactive invalidation.
When to use
Use to provide the invalidation service that refreshes queries, streams, and
atoms when application keys change.
Details
The service can register handlers for keys, invalidate those keys, wrap
mutations so successful effects invalidate keys, and turn query effects into
queues or streams that rerun when keys are invalidated.
Reactivity> =>
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 compiler: Statement.Compilerconst compiler: {
dialect: Dialect;
compile: (statement: Fragment, withoutTransform: boolean) => readonly [sql: string, params: ReadonlyArray<unknown>];
withoutTransform: this;
}
compiler = import StatementStatement.const makeCompilerSqlite: (
transform?: ((_: string) => string) | undefined
) => Statement.Compiler
Creates a SQLite compiler that uses ? placeholders and quoted identifiers,
optionally transforming identifier names before escaping.
makeCompilerSqlite(options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.transformQueryNames?: ((str: string) => string) | undefinedtransformQueryNames)
const const transformRows:
| (<A extends object>(
rows: ReadonlyArray<A>
) => ReadonlyArray<A>)
| undefined
transformRows = options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.transformResultNames?: ((str: string) => string) | undefinedtransformResultNames ?
import StatementStatement.const defaultTransforms: (
transformer: (str: string) => string,
nested?: boolean
) => {
readonly value: (value: any) => any
readonly object: (
obj: Record<string, any>
) => any
readonly array: <A extends object>(
rows: ReadonlyArray<A>
) => ReadonlyArray<A>
}
Builds value, object, and row-array transformers that rename object keys with
the supplied function and optionally recurse into nested object arrays.
defaultTransforms(
options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.transformResultNames?: (str: string) => stringtransformResultNames
).array: <A extends object>(
rows: ReadonlyArray<A>
) => ReadonlyArray<A>
array :
var undefinedundefined
const const makeConnection: Effect.Effect<
SqliteConnection,
never,
Scope.Scope
>
const makeConnection: {
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;
}
makeConnection = 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 scope: Scope.Scopeconst scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope = yield* import EffectEffect.const scope: Effect<Scope, never, Scope>const scope: {
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;
}
Returns the current scope for resource management.
Example (Accessing the current scope)
import { Console, Effect } from "effect"
const program = Effect.gen(function*() {
const currentScope = yield* Effect.scope
yield* Console.log("Got scope for resource management")
// Use the scope to manually manage resources if needed
const resource = yield* Effect.acquireRelease(
Console.log("Acquiring resource").pipe(Effect.as("resource")),
() => Console.log("Releasing resource")
)
return resource
})
Effect.runPromise(Effect.scoped(program)).then(console.log)
// Output:
// Got scope for resource management
// Acquiring resource
// resource
// Releasing resource
scope
const const db: anydb = new import DatabaseSyncDatabaseSync(options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.filename: stringfilename, {
readOnly: booleanreadOnly: options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.readonly?: boolean | undefinedreadonly ?? false,
allowExtension: booleanallowExtension: true
})
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(const scope: Scope.Scopeconst scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope, import EffectEffect.const sync: <A>(
thunk: LazyArg<A>
) => Effect<A>
Creates an Effect that represents a synchronous side-effectful computation.
When to use
Use when you need to wrap a synchronous side-effectful operation that is not
expected to throw.
Details
The provided function is evaluated lazily when the effect runs.
Gotchas
The function must not throw. If it throws, the thrown value is treated as a
defect, not as a typed failure. Use try when throwing is expected.
Example (Capturing synchronous logging in an Effect)
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")
sync(() => const db: anydb.close()))
const db: anydb.enableLoadExtension(false)
if (options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.disableWAL?: boolean | undefineddisableWAL !== true) {
const db: anydb.exec("PRAGMA journal_mode = WAL")
}
const const prepareCache: Cache.Cache<
string,
any,
SqlError,
never
>
const prepareCache: {
map: MutableHashMap.MutableHashMap<Key, Entry<A, E>>;
capacity: number;
lookup: (key: Key) => Effect.Effect<A, E, R>;
timeToLive: (exit: Exit.Exit<A, E>, key: Key) => Duration.Duration;
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; <…;
}
prepareCache = yield* import CacheCache.const make: <
Key,
A,
E = never,
R = never,
ServiceMode extends
| "lookup"
| "construction" = never
>(options: {
readonly lookup: (
key: Key
) => Effect.Effect<A, E, R>
readonly capacity: number
readonly timeToLive?: Duration.Input | undefined
readonly requireServicesAt?:
| ServiceMode
| undefined
}) => Effect.Effect<
Cache<
Key,
A,
E,
"lookup" extends ServiceMode ? R : never
>,
never,
"lookup" extends ServiceMode ? never : R
>
Creates a cache with a fixed time-to-live for all entries.
Details
This is the basic cache constructor where all entries share the same TTL.
The lookup function will be called when a key is not found or has expired.
Example (Creating a basic cache)
import { Cache, Effect } from "effect"
// Basic cache with string keys
const program = Effect.gen(function*() {
const cache = yield* Cache.make<string, number>({
capacity: 100,
lookup: (key) => Effect.succeed(key.length)
})
const result1 = yield* Cache.get(cache, "hello")
const result2 = yield* Cache.get(cache, "world")
console.log({ result1, result2 }) // { result1: 5, result2: 5 }
})
Example (Creating a cache with TTL)
import { Cache, Effect } from "effect"
const program = Effect.gen(function*() {
const users = new Map([
[123, { name: "Ada", email: "[email protected]" }],
[456, { name: "Grace", email: "[email protected]" }]
])
const cache = yield* Cache.make<
number,
{ name: string; email: string },
string
>({
capacity: 500,
lookup: (userId) =>
Effect.suspend(() => {
const user = users.get(userId)
return user === undefined
? Effect.fail(`User ${userId} not found`)
: Effect.succeed(user)
}),
timeToLive: "15 minutes"
})
const user1 = yield* Cache.get(cache, 123)
console.log(user1) // { name: "Ada", email: "[email protected]" }
const user2 = yield* Cache.get(cache, 123)
console.log(user2) // { name: "Ada", email: "[email protected]" }
})
make({
capacity: numbercapacity: options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.prepareCacheSize?: number | undefinedprepareCacheSize ?? 200,
timeToLive?: Duration.InputtimeToLive: options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.prepareCacheTTL?: Duration.Input | undefinedprepareCacheTTL ?? import DurationDuration.const minutes: (
minutes: number
) => Duration
Creates a Duration from minutes.
Example (Creating durations from minutes)
import { Duration } from "effect"
const duration = Duration.minutes(5)
console.log(Duration.toMillis(duration)) // 300000
minutes(10),
lookup: (
key: string
) => Effect.Effect<any, SqlError, never>
lookup: (sql: stringsql: string) =>
import EffectEffect.try<A, E = Cause.UnknownError>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E } | LazyArg<A>): Effect<A, E>Creates an Effect from a synchronous computation that may throw, mapping
thrown values into the error channel.
When to use
Use when you need to perform synchronous operations that might throw, such
as parsing JSON, and want thrown exceptions captured as Effect errors.
Details
The thunk is evaluated when the effect runs. If it returns normally, the
returned value becomes the success value. If it throws, the thrown 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.
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 (Parsing JSON)
import { Effect } from "effect"
const parseJSON = (input: string) =>
Effect.try(() => JSON.parse(input))
// Success case
Effect.runPromise(parseJSON("{\"name\": \"Alice\"}")).then(console.log)
// Output: { name: "Alice" }
// Failure case maps the thrown value to UnknownError
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
Example (Mapping exceptions to a tagged error)
import { Data, Effect } from "effect"
class JsonParsingError extends Data.TaggedError("JsonParsingError")<{ readonly cause: unknown }> {}
const parseJSON = (input: string) =>
Effect.try({
try: () => JSON.parse(input),
catch: (cause) => new JsonParsingError({ cause })
})
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
// Output: Exit.failure with custom Error message
try({
try: LazyArg<any>try: () => const db: anydb.prepare(sql: stringsql),
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) => new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to prepare statement", "prepare") })
})
})
const const runStatement: (
statement: StatementSync,
params: ReadonlyArray<unknown>,
raw: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
runStatement = (
statement: StatementSyncstatement: import StatementSyncStatementSync,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>,
raw: booleanraw: boolean
) =>
import EffectEffect.const withFiber: <
A,
E = never,
R = never
>(
evaluate: (
fiber: Fiber<unknown, unknown>
) => Effect<A, E, R>
) => Effect<A, E, R>
Provides access to the current fiber within an effect computation.
Example (Reading the current fiber)
import { Effect } from "effect"
const program = Effect.withFiber((fiber) =>
Effect.succeed(`Fiber ID: ${fiber.id}`)
)
Effect.runPromise(program).then(console.log)
// Output: Fiber ID: 1
withFiber<interface ReadonlyArray<T>ReadonlyArray<any>, class SqlErrorclass SqlError {
cause: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
message: string;
isRetryable: boolean;
_tag: 'SqlError';
reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
name: string;
stack: string;
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;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError>((fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber) => {
const const useSafeIntegers: booleanuseSafeIntegers = import ContextContext.const get: {
<Services, I extends Services, S>(
service: Key<I, S>
): (self: Context<Services>) => S
<Services, I extends Services, S>(
self: Context<Services>,
service: Key<I, S>
): S
}
Gets a service from the context that corresponds to the given key.
When to use
Use when you need type-checked access to a service already included in the
context type.
Example (Getting a service from a context)
import { Context, pipe } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const context = pipe(
Context.make(Port, { PORT: 8080 }),
Context.add(Timeout, { TIMEOUT: 5000 })
)
assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 })
get(fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber.Fiber<out A, out E = never>.context: Context.Context<never>(property) Fiber<out A, out E = never>.context: {
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;
}
context, import ClientClient.const SafeIntegers: Context.Reference<boolean>const SafeIntegers: {
defaultValue: () => Shape;
of: (this: void, self: boolean) => boolean;
context: (self: boolean) => Context.Context<never>;
use: (f: (service: boolean) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
useSync: (f: (service: boolean) => A) => Effect.Effect<A, never, never>;
Identifier: Identifier;
Service: Shape;
key: string;
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;
}
Context reference used by SQL integrations to opt in to safe integer
handling; defaults to false.
SafeIntegers)
return import EffectEffect.try<A, E = Cause.UnknownError>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E } | LazyArg<A>): Effect<A, E>Creates an Effect from a synchronous computation that may throw, mapping
thrown values into the error channel.
When to use
Use when you need to perform synchronous operations that might throw, such
as parsing JSON, and want thrown exceptions captured as Effect errors.
Details
The thunk is evaluated when the effect runs. If it returns normally, the
returned value becomes the success value. If it throws, the thrown 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.
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 (Parsing JSON)
import { Effect } from "effect"
const parseJSON = (input: string) =>
Effect.try(() => JSON.parse(input))
// Success case
Effect.runPromise(parseJSON("{\"name\": \"Alice\"}")).then(console.log)
// Output: { name: "Alice" }
// Failure case maps the thrown value to UnknownError
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
Example (Mapping exceptions to a tagged error)
import { Data, Effect } from "effect"
class JsonParsingError extends Data.TaggedError("JsonParsingError")<{ readonly cause: unknown }> {}
const parseJSON = (input: string) =>
Effect.try({
try: () => JSON.parse(input),
catch: (cause) => new JsonParsingError({ cause })
})
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
// Output: Exit.failure with custom Error message
try({
try: LazyArg<any>try: () => {
statement: StatementSyncstatement.setReadBigInts(const useSafeIntegers: booleanuseSafeIntegers)
if (statement: StatementSyncstatement.columns().length > 0) {
return statement: StatementSyncstatement.all(...(params: readonly unknown[]params as interface Array<T>Array<any>)) as interface ReadonlyArray<T>ReadonlyArray<any>
}
const const result: anyresult = statement: StatementSyncstatement.run(...(params: readonly unknown[]params as interface Array<T>Array<any>))
return raw: booleanraw ? { changes: anychanges: const result: anyresult.changes, lastInsertRowid: anylastInsertRowid: const result: anyresult.lastInsertRowid } as any : []
},
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) => new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to execute statement", "execute") })
})
})
const const runStatementValues: (
statement: StatementSync,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runStatementValues = (
statement: StatementSyncstatement: import StatementSyncStatementSync,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>
) =>
import EffectEffect.const withFiber: <
A,
E = never,
R = never
>(
evaluate: (
fiber: Fiber<unknown, unknown>
) => Effect<A, E, R>
) => Effect<A, E, R>
Provides access to the current fiber within an effect computation.
Example (Reading the current fiber)
import { Effect } from "effect"
const program = Effect.withFiber((fiber) =>
Effect.succeed(`Fiber ID: ${fiber.id}`)
)
Effect.runPromise(program).then(console.log)
// Output: Fiber ID: 1
withFiber<interface ReadonlyArray<T>ReadonlyArray<interface ReadonlyArray<T>ReadonlyArray<unknown>>, class SqlErrorclass SqlError {
cause: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
message: string;
isRetryable: boolean;
_tag: 'SqlError';
reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
name: string;
stack: string;
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;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError>((fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber) => {
const const useSafeIntegers: booleanuseSafeIntegers = import ContextContext.const get: {
<Services, I extends Services, S>(
service: Key<I, S>
): (self: Context<Services>) => S
<Services, I extends Services, S>(
self: Context<Services>,
service: Key<I, S>
): S
}
Gets a service from the context that corresponds to the given key.
When to use
Use when you need type-checked access to a service already included in the
context type.
Example (Getting a service from a context)
import { Context, pipe } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const context = pipe(
Context.make(Port, { PORT: 8080 }),
Context.add(Timeout, { TIMEOUT: 5000 })
)
assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 })
get(fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber.Fiber<out A, out E = never>.context: Context.Context<never>(property) Fiber<out A, out E = never>.context: {
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;
}
context, import ClientClient.const SafeIntegers: Context.Reference<boolean>const SafeIntegers: {
defaultValue: () => Shape;
of: (this: void, self: boolean) => boolean;
context: (self: boolean) => Context.Context<never>;
use: (f: (service: boolean) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
useSync: (f: (service: boolean) => A) => Effect.Effect<A, never, never>;
Identifier: Identifier;
Service: Shape;
key: string;
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;
}
Context reference used by SQL integrations to opt in to safe integer
handling; defaults to false.
SafeIntegers)
return import EffectEffect.try<A, E = Cause.UnknownError>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E } | LazyArg<A>): Effect<A, E>Creates an Effect from a synchronous computation that may throw, mapping
thrown values into the error channel.
When to use
Use when you need to perform synchronous operations that might throw, such
as parsing JSON, and want thrown exceptions captured as Effect errors.
Details
The thunk is evaluated when the effect runs. If it returns normally, the
returned value becomes the success value. If it throws, the thrown 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.
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 (Parsing JSON)
import { Effect } from "effect"
const parseJSON = (input: string) =>
Effect.try(() => JSON.parse(input))
// Success case
Effect.runPromise(parseJSON("{\"name\": \"Alice\"}")).then(console.log)
// Output: { name: "Alice" }
// Failure case maps the thrown value to UnknownError
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
Example (Mapping exceptions to a tagged error)
import { Data, Effect } from "effect"
class JsonParsingError extends Data.TaggedError("JsonParsingError")<{ readonly cause: unknown }> {}
const parseJSON = (input: string) =>
Effect.try({
try: () => JSON.parse(input),
catch: (cause) => new JsonParsingError({ cause })
})
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
// Output: Exit.failure with custom Error message
try({
try: LazyArg<readonly (readonly unknown[])[]>try: () => {
statement: StatementSyncstatement.setReadBigInts(const useSafeIntegers: booleanuseSafeIntegers)
if (statement: StatementSyncstatement.columns().length > 0) {
return statement: StatementSyncstatement.all(...(params: readonly unknown[]params as interface Array<T>Array<any>)) as unknown as interface ReadonlyArray<T>ReadonlyArray<interface ReadonlyArray<T>ReadonlyArray<unknown>>
}
statement: StatementSyncstatement.run(...(params: readonly unknown[]params as interface Array<T>Array<any>))
return []
},
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) => new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to execute statement", "execute") })
})
})
const const runStatementValuesUnprepared: (
statement: StatementSync,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runStatementValuesUnprepared = (
statement: StatementSyncstatement: import StatementSyncStatementSync,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>
) =>
import EffectEffect.const withFiber: <
A,
E = never,
R = never
>(
evaluate: (
fiber: Fiber<unknown, unknown>
) => Effect<A, E, R>
) => Effect<A, E, R>
Provides access to the current fiber within an effect computation.
Example (Reading the current fiber)
import { Effect } from "effect"
const program = Effect.withFiber((fiber) =>
Effect.succeed(`Fiber ID: ${fiber.id}`)
)
Effect.runPromise(program).then(console.log)
// Output: Fiber ID: 1
withFiber<interface ReadonlyArray<T>ReadonlyArray<interface ReadonlyArray<T>ReadonlyArray<unknown>>, class SqlErrorclass SqlError {
cause: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
message: string;
isRetryable: boolean;
_tag: 'SqlError';
reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
name: string;
stack: string;
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;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError>((fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber) => {
const const useSafeIntegers: booleanuseSafeIntegers = import ContextContext.const get: {
<Services, I extends Services, S>(
service: Key<I, S>
): (self: Context<Services>) => S
<Services, I extends Services, S>(
self: Context<Services>,
service: Key<I, S>
): S
}
Gets a service from the context that corresponds to the given key.
When to use
Use when you need type-checked access to a service already included in the
context type.
Example (Getting a service from a context)
import { Context, pipe } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const context = pipe(
Context.make(Port, { PORT: 8080 }),
Context.add(Timeout, { TIMEOUT: 5000 })
)
assert.deepStrictEqual(Context.get(context, Timeout), { TIMEOUT: 5000 })
get(fiber: Fiber.Fiber<unknown, unknown>(parameter) fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber.Fiber<out A, out E = never>.context: Context.Context<never>(property) Fiber<out A, out E = never>.context: {
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;
}
context, import ClientClient.const SafeIntegers: Context.Reference<boolean>const SafeIntegers: {
defaultValue: () => Shape;
of: (this: void, self: boolean) => boolean;
context: (self: boolean) => Context.Context<never>;
use: (f: (service: boolean) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
useSync: (f: (service: boolean) => A) => Effect.Effect<A, never, never>;
Identifier: Identifier;
Service: Shape;
key: string;
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;
}
Context reference used by SQL integrations to opt in to safe integer
handling; defaults to false.
SafeIntegers)
return import EffectEffect.try<A, E = Cause.UnknownError>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E } | LazyArg<A>): Effect<A, E>Creates an Effect from a synchronous computation that may throw, mapping
thrown values into the error channel.
When to use
Use when you need to perform synchronous operations that might throw, such
as parsing JSON, and want thrown exceptions captured as Effect errors.
Details
The thunk is evaluated when the effect runs. If it returns normally, the
returned value becomes the success value. If it throws, the thrown 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.
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 (Parsing JSON)
import { Effect } from "effect"
const parseJSON = (input: string) =>
Effect.try(() => JSON.parse(input))
// Success case
Effect.runPromise(parseJSON("{\"name\": \"Alice\"}")).then(console.log)
// Output: { name: "Alice" }
// Failure case maps the thrown value to UnknownError
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
Example (Mapping exceptions to a tagged error)
import { Data, Effect } from "effect"
class JsonParsingError extends Data.TaggedError("JsonParsingError")<{ readonly cause: unknown }> {}
const parseJSON = (input: string) =>
Effect.try({
try: () => JSON.parse(input),
catch: (cause) => new JsonParsingError({ cause })
})
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
// Output: Exit.failure with custom Error message
try({
try: LazyArg<readonly (readonly unknown[])[]>try: () => {
statement: StatementSyncstatement.setReadBigInts(const useSafeIntegers: booleanuseSafeIntegers)
statement: StatementSyncstatement.setReturnArrays(true)
if (statement: StatementSyncstatement.columns().length > 0) {
return statement: StatementSyncstatement.all(...(params: readonly unknown[]params as interface Array<T>Array<any>)) as unknown as interface ReadonlyArray<T>ReadonlyArray<interface ReadonlyArray<T>ReadonlyArray<unknown>>
}
statement: StatementSyncstatement.run(...(params: readonly unknown[]params as interface Array<T>Array<any>))
return []
},
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) => new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to execute statement", "execute") })
})
})
const const run: (
sql: string,
params: ReadonlyArray<unknown>,
raw?: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
run = (
sql: stringsql: string,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>,
raw: booleanraw = false
) =>
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>
}
Chains effects to produce new Effect instances, useful for combining
operations that depend on previous results.
When to use
Use when you need to chain multiple effects, ensuring that each
step produces a new Effect while flattening any nested effects that may
occur.
Details
flatMap lets you sequence effects so that the result of one effect can be
used in the next step. It is similar to flatMap used with arrays but works
specifically with Effect instances, allowing you to avoid deeply nested
effect structures.
Since effects are immutable, flatMap always returns a new effect instead of
changing the original one.
Example (Choosing flatMap syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => Effect.succeed(n + 1)
const flatMappedWithPipe = pipe(myEffect, Effect.flatMap(transformation))
const flatMappedWithDataFirst = Effect.flatMap(myEffect, transformation)
const flatMappedWithMethod = myEffect.pipe(Effect.flatMap(transformation))
Example (Sequencing dependent effects)
import { Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Chaining the fetch and discount application using `flatMap`
const finalAmount = pipe(
fetchTransactionAmount,
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 95
flatMap(
import CacheCache.const get: {
<Key, A>(key: Key): <E, R>(
self: Cache<Key, A, E, R>
) => Effect.Effect<A, E, R>
<Key, A, E, R>(
self: Cache<Key, A, E, R>,
key: Key
): Effect.Effect<A, E, R>
}
Retrieves the value for a key, invoking the lookup function on a cache miss
or expired entry.
Details
Concurrent get calls for the same missing key share the same pending
lookup. The cache stores the lookup Exit, so failed lookups are cached and
will fail again until the entry expires, is invalidated, or is refreshed.
Example (Getting cached values)
import { Cache, Effect } from "effect"
const program = Effect.gen(function*() {
const cache = yield* Cache.make({
capacity: 10,
lookup: (key: string) => Effect.succeed(key.length)
})
// Cache miss - triggers lookup function
const result1 = yield* Cache.get(cache, "hello")
console.log(result1) // 5
// Cache hit - returns cached value without lookup
const result2 = yield* Cache.get(cache, "hello")
console.log(result2) // 5 (from cache)
return { result1, result2 }
})
Example (Handling lookup failures)
import { Cache, Effect } from "effect"
// Error handling when lookup fails
const program = Effect.gen(function*() {
const cache = yield* Cache.make<string, number, string>({
capacity: 10,
lookup: (key: string) =>
key === "error"
? Effect.fail("Lookup failed")
: Effect.succeed(key.length)
})
// Successful lookup
const success = yield* Cache.get(cache, "hello")
console.log(success) // 5
// Failed lookup - returns error
const failure = yield* Effect.exit(Cache.get(cache, "error"))
console.log(failure) // Exit.fail("Lookup failed")
})
Example (Sharing concurrent lookups)
import { Cache, Effect } from "effect"
// Concurrent access - multiple gets of same key only invoke lookup once
const program = Effect.gen(function*() {
let lookupCount = 0
const cache = yield* Cache.make({
capacity: 10,
lookup: (key: string) =>
Effect.sync(() => {
lookupCount++
return key.length
})
})
// Multiple concurrent gets
const results = yield* Effect.all([
Cache.get(cache, "hello"),
Cache.get(cache, "hello"),
Cache.get(cache, "hello")
], { concurrency: "unbounded" })
console.log(results) // [5, 5, 5]
console.log(lookupCount) // 1 (lookup called only once)
})
get(const prepareCache: Cache.Cache<
string,
any,
SqlError,
never
>
const prepareCache: {
map: MutableHashMap.MutableHashMap<Key, Entry<A, E>>;
capacity: number;
lookup: (key: Key) => Effect.Effect<A, E, R>;
timeToLive: (exit: Exit.Exit<A, E>, key: Key) => Duration.Duration;
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; <…;
}
prepareCache, sql: stringsql),
(s: anys) => const runStatement: (
statement: StatementSync,
params: ReadonlyArray<unknown>,
raw: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
runStatement(s: anys, params: readonly unknown[]params, raw: booleanraw)
)
const const runValues: (
sql: string,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runValues = (
sql: stringsql: string,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>
) =>
import EffectEffect.const acquireUseRelease: <
Resource,
E,
R,
A,
E2,
R2,
E3,
R3
>(
acquire: Effect<Resource, E, R>,
use: (a: Resource) => Effect<A, E2, R2>,
release: (
a: Resource,
exit: Exit.Exit<A, E2>
) => Effect<void, E3, R3>
) => Effect<A, E | E2 | E3, R | R2 | R3>
Runs resource acquisition, usage, and release as one bracketed effect.
When to use
Use to bracket acquire, use, and release logic in one effect.
Details
acquireUseRelease does the following:
- Ensures that the
Effect value that acquires the resource will not be
interrupted. Note that acquisition may still fail due to internal
reasons (such as an uncaught exception).
- Ensures that the
release Effect value will not be interrupted,
and will be executed as long as the acquisition Effect value
successfully acquires the resource.
During the time period between the acquisition and release of the resource,
the use Effect value will be executed.
If the release Effect value fails, then the entire Effect value will
fail, even if the use Effect value succeeds. If this fail-fast behavior
is not desired, errors produced by the release Effect value can be caught
and ignored.
Example (Acquiring resources with cleanup)
import { Console, Effect, Exit } from "effect"
interface Database {
readonly connection: string
readonly query: (sql: string) => Effect.Effect<string>
}
const program = Effect.acquireUseRelease(
// Acquire - connect to database
Effect.gen(function*() {
yield* Console.log("Connecting to database...")
return {
connection: "db://localhost:5432",
query: (sql: string) => Effect.succeed(`Result for: ${sql}`)
}
}),
// Use - perform database operations
(db) =>
Effect.gen(function*() {
yield* Console.log(`Connected to ${db.connection}`)
const result = yield* db.query("SELECT * FROM users")
yield* Console.log(`Query result: ${result}`)
return result
}),
// Release - close database connection
(db, exit) =>
Effect.gen(function*() {
if (Exit.isSuccess(exit)) {
yield* Console.log(`Closing connection to ${db.connection} (success)`)
} else {
yield* Console.log(`Closing connection to ${db.connection} (failure)`)
}
})
)
Effect.runPromise(program)
// Output:
// Connecting to database...
// Connected to db://localhost:5432
// Query result: Result for: SELECT * FROM users
// Closing connection to db://localhost:5432 (success)
acquireUseRelease(
import CacheCache.const get: {
<Key, A>(key: Key): <E, R>(
self: Cache<Key, A, E, R>
) => Effect.Effect<A, E, R>
<Key, A, E, R>(
self: Cache<Key, A, E, R>,
key: Key
): Effect.Effect<A, E, R>
}
Retrieves the value for a key, invoking the lookup function on a cache miss
or expired entry.
Details
Concurrent get calls for the same missing key share the same pending
lookup. The cache stores the lookup Exit, so failed lookups are cached and
will fail again until the entry expires, is invalidated, or is refreshed.
Example (Getting cached values)
import { Cache, Effect } from "effect"
const program = Effect.gen(function*() {
const cache = yield* Cache.make({
capacity: 10,
lookup: (key: string) => Effect.succeed(key.length)
})
// Cache miss - triggers lookup function
const result1 = yield* Cache.get(cache, "hello")
console.log(result1) // 5
// Cache hit - returns cached value without lookup
const result2 = yield* Cache.get(cache, "hello")
console.log(result2) // 5 (from cache)
return { result1, result2 }
})
Example (Handling lookup failures)
import { Cache, Effect } from "effect"
// Error handling when lookup fails
const program = Effect.gen(function*() {
const cache = yield* Cache.make<string, number, string>({
capacity: 10,
lookup: (key: string) =>
key === "error"
? Effect.fail("Lookup failed")
: Effect.succeed(key.length)
})
// Successful lookup
const success = yield* Cache.get(cache, "hello")
console.log(success) // 5
// Failed lookup - returns error
const failure = yield* Effect.exit(Cache.get(cache, "error"))
console.log(failure) // Exit.fail("Lookup failed")
})
Example (Sharing concurrent lookups)
import { Cache, Effect } from "effect"
// Concurrent access - multiple gets of same key only invoke lookup once
const program = Effect.gen(function*() {
let lookupCount = 0
const cache = yield* Cache.make({
capacity: 10,
lookup: (key: string) =>
Effect.sync(() => {
lookupCount++
return key.length
})
})
// Multiple concurrent gets
const results = yield* Effect.all([
Cache.get(cache, "hello"),
Cache.get(cache, "hello"),
Cache.get(cache, "hello")
], { concurrency: "unbounded" })
console.log(results) // [5, 5, 5]
console.log(lookupCount) // 1 (lookup called only once)
})
get(const prepareCache: Cache.Cache<
string,
any,
SqlError,
never
>
const prepareCache: {
map: MutableHashMap.MutableHashMap<Key, Entry<A, E>>;
capacity: number;
lookup: (key: Key) => Effect.Effect<A, E, R>;
timeToLive: (exit: Exit.Exit<A, E>, key: Key) => Duration.Duration;
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; <…;
}
prepareCache, sql: stringsql),
(statement: anystatement) => {
statement: anystatement.setReturnArrays(true)
return const runStatementValues: (
statement: StatementSync,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runStatementValues(statement: anystatement, params: readonly unknown[]params)
},
(statement: anystatement) => import EffectEffect.const sync: <A>(
thunk: LazyArg<A>
) => Effect<A>
Creates an Effect that represents a synchronous side-effectful computation.
When to use
Use when you need to wrap a synchronous side-effectful operation that is not
expected to throw.
Details
The provided function is evaluated lazily when the effect runs.
Gotchas
The function must not throw. If it throws, the thrown value is treated as a
defect, not as a typed failure. Use try when throwing is expected.
Example (Capturing synchronous logging in an Effect)
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")
sync(() => statement: anystatement.setReturnArrays(false))
)
const const runValuesUnprepared: (
sql: string,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runValuesUnprepared = (
sql: stringsql: string,
params: readonly unknown[]params: interface ReadonlyArray<T>ReadonlyArray<unknown>
) => const runStatementValuesUnprepared: (
statement: StatementSync,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runStatementValuesUnprepared(const db: anydb.prepare(sql: stringsql), params: readonly unknown[]params)
return identity<SqliteConnection>(a: SqliteConnection): SqliteConnectionReturns its input argument unchanged.
When to use
Use to return a value unchanged where a function is required.
Example (Returning the same value)
import { identity } from "effect"
import * as assert from "node:assert"
assert.deepStrictEqual(identity(5), 5)
identity<SqliteConnection>({
Connection.execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect.Effect<ReadonlyArray<any>, SqlError>execute(sql: stringsql, params: readonly unknown[]params, transformRows: | (<A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>)
| undefined
transformRows) {
return transformRows: | (<A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>)
| undefined
transformRows
? import EffectEffect.const map: {
<A, B>(f: (a: A) => B): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E, R>
<A, E, R, B>(
self: Effect<A, E, R>,
f: (a: A) => B
): Effect<B, E, R>
}
Transforms the value inside an effect by applying a function to it.
When to use
Use to transform an effect's success value with a function that returns a
plain value, producing a new effect without changing the original effect's
typed error or context requirements.
Details
map takes a function and applies it to the value contained within an
effect, creating a new effect with the transformed value.
It's important to note that effects are immutable, meaning that the original
effect is not modified. Instead, a new effect is returned with the updated
value.
Example (Choosing map syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => n + 1
const mappedWithPipe = pipe(myEffect, Effect.map(transformation))
const mappedWithDataFirst = Effect.map(myEffect, transformation)
const mappedWithMethod = myEffect.pipe(Effect.map(transformation))
Example (Adding a service charge)
import { Effect, pipe } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
Effect.map(addServiceCharge)
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
map(const run: (
sql: string,
params: ReadonlyArray<unknown>,
raw?: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
run(sql: stringsql, params: readonly unknown[]params), transformRows: <A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>
transformRows)
: const run: (
sql: string,
params: ReadonlyArray<unknown>,
raw?: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
run(sql: stringsql, params: readonly unknown[]params)
},
Connection.executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect.Effect<unknown, SqlError>Execute the specified SQL query and return the raw results directly from
underlying SQL client.
executeRaw(sql: stringsql, params: readonly unknown[]params) {
return const run: (
sql: string,
params: ReadonlyArray<unknown>,
raw?: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
run(sql: stringsql, params: readonly unknown[]params, true)
},
Connection.executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect.Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>executeValues(sql: stringsql, params: readonly unknown[]params) {
return const runValues: (
sql: string,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runValues(sql: stringsql, params: readonly unknown[]params)
},
Connection.executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect.Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>executeValuesUnprepared(sql: stringsql, params: readonly unknown[]params) {
return const runValuesUnprepared: (
sql: string,
params: ReadonlyArray<unknown>
) => Effect.Effect<
readonly (readonly unknown[])[],
SqlError,
never
>
runValuesUnprepared(sql: stringsql, params: readonly unknown[]params)
},
Connection.executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect.Effect<ReadonlyArray<any>, SqlError>executeUnprepared(sql: stringsql, params: readonly unknown[]params, transformRows: | (<A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>)
| undefined
transformRows) {
const const effect: Effect.Effect<
ReadonlyArray<any>,
SqlError,
never
>
const effect: {
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;
}
effect = const runStatement: (
statement: StatementSync,
params: ReadonlyArray<unknown>,
raw: boolean
) => Effect.Effect<
readonly any[],
SqlError,
never
>
runStatement(const db: anydb.prepare(sql: stringsql), params: readonly unknown[]params ?? [], false)
return transformRows: | (<A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>)
| undefined
transformRows ? import EffectEffect.const map: {
<A, B>(f: (a: A) => B): <E, R>(
self: Effect<A, E, R>
) => Effect<B, E, R>
<A, E, R, B>(
self: Effect<A, E, R>,
f: (a: A) => B
): Effect<B, E, R>
}
Transforms the value inside an effect by applying a function to it.
When to use
Use to transform an effect's success value with a function that returns a
plain value, producing a new effect without changing the original effect's
typed error or context requirements.
Details
map takes a function and applies it to the value contained within an
effect, creating a new effect with the transformed value.
It's important to note that effects are immutable, meaning that the original
effect is not modified. Instead, a new effect is returned with the updated
value.
Example (Choosing map syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => n + 1
const mappedWithPipe = pipe(myEffect, Effect.map(transformation))
const mappedWithDataFirst = Effect.map(myEffect, transformation)
const mappedWithMethod = myEffect.pipe(Effect.map(transformation))
Example (Adding a service charge)
import { Effect, pipe } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
Effect.map(addServiceCharge)
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 101
map(const effect: Effect.Effect<
ReadonlyArray<any>,
SqlError,
never
>
const effect: {
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;
}
effect, transformRows: <A extends object>(
row: ReadonlyArray<A>
) => ReadonlyArray<A>
transformRows) : const effect: Effect.Effect<
ReadonlyArray<any>,
SqlError,
never
>
const effect: {
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;
}
effect
},
Connection.executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream.Stream<any, SqlError>executeStream(_sql: string_sql, _params: readonly unknown[]_params) {
return import StreamStream.const die: (
defect: unknown
) => Stream<never>
The stream that dies with the specified defect.
Example (Dying with a defect)
import { Cause, Console, Effect, Exit, Stream } from "effect"
const defect = new Error("Boom")
const stream = Stream.die(defect)
const program = Effect.gen(function*() {
const exit = yield* Effect.exit(Stream.runCollect(stream))
const message = Exit.match(exit, {
onSuccess: () => "Exit.Success",
onFailure: (cause) => {
const reason = cause.reasons[0]
const defect = Cause.isDieReason(reason) ? String(reason.defect) : "Unexpected reason"
return `Exit.Failure(${defect})`
}
})
yield* Console.log(message)
})
Effect.runPromise(program)
// Output: Exit.Failure(Error: Boom)
die("executeStream not implemented")
},
SqliteConnection.backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>backup(destination: stringdestination) {
return import EffectEffect.const suspend: <A, E, R>(
effect: LazyArg<Effect<A, E, R>>
) => Effect<A, E, R>
Creates an Effect lazily, delaying construction until it is needed.
When to use
Use when you need to defer the evaluation of an effect until it is required.
Details
suspend takes a thunk that represents an effect and delays creating it
until the suspended effect is evaluated. This is useful for optimizing
expensive computations, managing circular dependencies such as recursive
functions, and helping TypeScript unify return types when branches construct
different effects. Any side effects or scoped captures inside the thunk are
re-executed on each invocation.
Example (Lazily evaluating side effects)
import { Effect } from "effect"
let i = 0
const bad = Effect.succeed(i++)
const good = Effect.suspend(() => Effect.succeed(i++))
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(bad)) // Output: 0
console.log(Effect.runSync(good)) // Output: 1
console.log(Effect.runSync(good)) // Output: 2
Example (Suspending recursive Fibonacci evaluation)
import { Effect } from "effect"
const blowsUp = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(1)
: Effect.zipWith(blowsUp(n - 1), blowsUp(n - 2), (a, b) => a + b)
// console.log(Effect.runSync(blowsUp(32)))
// crash: JavaScript heap out of memory
const allGood = (n: number): Effect.Effect<number> =>
n < 2
? Effect.succeed(1)
: Effect.zipWith(
Effect.suspend(() => allGood(n - 1)),
Effect.suspend(() => allGood(n - 2)),
(a, b) => a + b
)
console.log(Effect.runSync(allGood(32)))
// Output: 3524578
Example (Helping TypeScript infer recursive effect types)
import { Effect } from "effect"
// Without suspend, TypeScript may struggle with type inference.
// Inferred type:
// (a: number, b: number) =>
// Effect<never, Error, never> | Effect<number, never, never>
const withoutSuspend = (a: number, b: number) =>
b === 0
? Effect.fail(new Error("Cannot divide by zero"))
: Effect.succeed(a / b)
// Using suspend to unify return types.
// Inferred type:
// (a: number, b: number) => Effect<number, Error, never>
const withSuspend = (a: number, b: number) =>
Effect.suspend(() =>
b === 0
? Effect.fail(new Error("Cannot divide by zero"))
: Effect.succeed(a / b)
)
suspend(() => {
let let totalPages: numbertotalPages = 0
return 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<BackupMetadata>
try: () =>
import backupDatabasebackupDatabase(const db: anydb, destination: stringdestination, {
progress: (progress: any) => voidprogress: (progress: anyprogress) => {
let totalPages: numbertotalPages = progress: anyprogress.totalPages
}
}).then((pages: anypages): BackupMetadata => ({ BackupMetadata.totalPages: numbertotalPages: let totalPages: numbertotalPages || pages: anypages, BackupMetadata.remainingPages: numberremainingPages: 0 })),
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) => new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to backup database", "backup") })
})
})
},
SqliteConnection.loadExtension: (path: string) => Effect.Effect<void, SqlError>loadExtension(path: stringpath) {
return import EffectEffect.const acquireUseRelease: <
Resource,
E,
R,
A,
E2,
R2,
E3,
R3
>(
acquire: Effect<Resource, E, R>,
use: (a: Resource) => Effect<A, E2, R2>,
release: (
a: Resource,
exit: Exit.Exit<A, E2>
) => Effect<void, E3, R3>
) => Effect<A, E | E2 | E3, R | R2 | R3>
Runs resource acquisition, usage, and release as one bracketed effect.
When to use
Use to bracket acquire, use, and release logic in one effect.
Details
acquireUseRelease does the following:
- Ensures that the
Effect value that acquires the resource will not be
interrupted. Note that acquisition may still fail due to internal
reasons (such as an uncaught exception).
- Ensures that the
release Effect value will not be interrupted,
and will be executed as long as the acquisition Effect value
successfully acquires the resource.
During the time period between the acquisition and release of the resource,
the use Effect value will be executed.
If the release Effect value fails, then the entire Effect value will
fail, even if the use Effect value succeeds. If this fail-fast behavior
is not desired, errors produced by the release Effect value can be caught
and ignored.
Example (Acquiring resources with cleanup)
import { Console, Effect, Exit } from "effect"
interface Database {
readonly connection: string
readonly query: (sql: string) => Effect.Effect<string>
}
const program = Effect.acquireUseRelease(
// Acquire - connect to database
Effect.gen(function*() {
yield* Console.log("Connecting to database...")
return {
connection: "db://localhost:5432",
query: (sql: string) => Effect.succeed(`Result for: ${sql}`)
}
}),
// Use - perform database operations
(db) =>
Effect.gen(function*() {
yield* Console.log(`Connected to ${db.connection}`)
const result = yield* db.query("SELECT * FROM users")
yield* Console.log(`Query result: ${result}`)
return result
}),
// Release - close database connection
(db, exit) =>
Effect.gen(function*() {
if (Exit.isSuccess(exit)) {
yield* Console.log(`Closing connection to ${db.connection} (success)`)
} else {
yield* Console.log(`Closing connection to ${db.connection} (failure)`)
}
})
)
Effect.runPromise(program)
// Output:
// Connecting to database...
// Connected to db://localhost:5432
// Query result: Result for: SELECT * FROM users
// Closing connection to db://localhost:5432 (success)
acquireUseRelease(
import EffectEffect.const sync: <A>(
thunk: LazyArg<A>
) => Effect<A>
Creates an Effect that represents a synchronous side-effectful computation.
When to use
Use when you need to wrap a synchronous side-effectful operation that is not
expected to throw.
Details
The provided function is evaluated lazily when the effect runs.
Gotchas
The function must not throw. If it throws, the thrown value is treated as a
defect, not as a typed failure. Use try when throwing is expected.
Example (Capturing synchronous logging in an Effect)
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")
sync(() => const db: anydb.enableLoadExtension(true)),
() =>
import EffectEffect.try<A, E = Cause.UnknownError>(options: { readonly try: LazyArg<A>; readonly catch: (error: unknown) => E } | LazyArg<A>): Effect<A, E>Creates an Effect from a synchronous computation that may throw, mapping
thrown values into the error channel.
When to use
Use when you need to perform synchronous operations that might throw, such
as parsing JSON, and want thrown exceptions captured as Effect errors.
Details
The thunk is evaluated when the effect runs. If it returns normally, the
returned value becomes the success value. If it throws, the thrown 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.
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 (Parsing JSON)
import { Effect } from "effect"
const parseJSON = (input: string) =>
Effect.try(() => JSON.parse(input))
// Success case
Effect.runPromise(parseJSON("{\"name\": \"Alice\"}")).then(console.log)
// Output: { name: "Alice" }
// Failure case maps the thrown value to UnknownError
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
Example (Mapping exceptions to a tagged error)
import { Data, Effect } from "effect"
class JsonParsingError extends Data.TaggedError("JsonParsingError")<{ readonly cause: unknown }> {}
const parseJSON = (input: string) =>
Effect.try({
try: () => JSON.parse(input),
catch: (cause) => new JsonParsingError({ cause })
})
Effect.runPromiseExit(parseJSON("invalid json")).then(console.log)
// Output: Exit.failure with custom Error message
try({
try: LazyArg<any>try: () => const db: anydb.loadExtension(path: stringpath),
catch: (error: unknown) => SqlErrorcatch: (cause: unknowncause) =>
new new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): SqlError
(alias) new SqlError(props: {
readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError;
readonly _tag?: "SqlError" | undefined;
}, options?: MakeOptions | undefined): {
Type: Self;
Encoded: S["Encoded"];
DecodingServices: S["DecodingServices"];
EncodingServices: S["EncodingServices"];
Iso: S["Iso"];
identifier: string;
fields: S["fields"];
mapFields: (f: (fields: { readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof ConstraintError, typeof DeadlockErr…;
extend: (identifier: string) => { (fields: NewFields, annotations?: Annotations.Declaration<Extended, readonly [Struct<{ [K in keyof { [K in keyof (('_tag' | 'reason') & keyof NewFields extends never ? { readonly _tag: tag<'SqlError'>; readonly re…;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<SqlError, readonly [TaggedStruct<'SqlError', { readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError, typeof UniqueViolation, typeof Co…;
annotateKey: (annotations: Annotations.Key<SqlError>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, …;
check: (checks_0: Check<SqlError>, ...checks: Array<Check<SqlError>>) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeo…;
rebuild: (ast: Declaration) => decodeTo<declareConstructor<SqlError, Struct.ReadonlySide<{ readonly _tag: tag<'SqlError'>; readonly reason: Union<[typeof ConnectionError, typeof AuthenticationError, typeof AuthorizationError, typeof SqlSyntaxError,…;
make: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeOption: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
makeEffect: (input: { readonly reason: ConnectionError | AuthenticationError | AuthorizationError | SqlSyntaxError | UniqueViolation | ConstraintError | DeadlockError | SerializationError | LockTimeoutError | StatementTimeoutError | UnknownError; read…;
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; <…;
}
Error wrapper for SQL failures whose message, cause, and isRetryable
values are derived from its SqlErrorReason.
SqlError({ reason: | ConnectionError
| AuthenticationError
| AuthorizationError
| SqlSyntaxError
| UniqueViolation
| ConstraintError
| DeadlockError
| SerializationError
| LockTimeoutError
| StatementTimeoutError
| UnknownError
reason: const classifyError: (
cause: unknown,
message: string,
operation: string
) => SqlErrorReason
classifyError(cause: unknowncause, "Failed to load extension", "loadExtension") })
}),
() => import EffectEffect.const sync: <A>(
thunk: LazyArg<A>
) => Effect<A>
Creates an Effect that represents a synchronous side-effectful computation.
When to use
Use when you need to wrap a synchronous side-effectful operation that is not
expected to throw.
Details
The provided function is evaluated lazily when the effect runs.
Gotchas
The function must not throw. If it throws, the thrown value is treated as a
defect, not as a typed failure. Use try when throwing is expected.
Example (Capturing synchronous logging in an Effect)
import { Effect } from "effect"
const log = (message: string) =>
Effect.sync(() => {
console.log(message) // side effect
})
// ┌─── Effect<void, never, never>
// ▼
const program = log("Hello, World!")
sync(() => const db: anydb.enableLoadExtension(false))
)
}
})
})
const const semaphore: Semaphore.Semaphoreconst semaphore: {
resize: (this: Semaphore, permits: number) => Effect.Effect<void>;
withPermits: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermit: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermitsIfAvailable: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>;
take: (this: Semaphore, permits: number) => Effect.Effect<number>;
release: (this: Semaphore, permits: number) => Effect.Effect<number>;
releaseAll: Effect.Effect<number>;
}
semaphore = yield* import SemaphoreSemaphore.const make: (
permits: number
) => Effect.Effect<Semaphore>
Creates a Semaphore initialized with the specified total number of permits.
When to use
Use to create a semaphore inside Effect code for bounding concurrency with
automatic or manual permit management.
Example (Creating a semaphore)
import { Effect, Semaphore } from "effect"
const program = Effect.gen(function*() {
const semaphore = yield* Semaphore.make(2)
const task = (id: number) =>
semaphore.withPermits(1)(
Effect.gen(function*() {
yield* Effect.log(`Task ${id} acquired permit`)
yield* Effect.sleep("1 second")
yield* Effect.log(`Task ${id} releasing permit`)
})
)
// Run 4 tasks, but only 2 can run concurrently
yield* Effect.all([task(1), task(2), task(3), task(4)])
})
make(1)
const const connection: SqliteConnectionconst connection: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
connection = yield* const makeConnection: Effect.Effect<
SqliteConnection,
never,
Scope.Scope
>
const makeConnection: {
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;
}
makeConnection
const const acquirer: Effect.Effect<
SqliteConnection,
never,
never
>
const acquirer: {
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;
}
acquirer = const semaphore: Semaphore.Semaphoreconst semaphore: {
resize: (this: Semaphore, permits: number) => Effect.Effect<void>;
withPermits: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermit: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermitsIfAvailable: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>;
take: (this: Semaphore, permits: number) => Effect.Effect<number>;
release: (this: Semaphore, permits: number) => Effect.Effect<number>;
releaseAll: Effect.Effect<number>;
}
semaphore.Semaphore.withPermits(this: Semaphore, permits: number): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>Runs an effect with the given number of permits and releases the permits
when the effect completes.
When to use
Use to run an effect while holding a specified number of semaphore permits.
Details
This function acquires the specified number of permits before executing
the provided effect. Once the effect finishes, the permits are released.
If insufficient permits are available, the function will wait until they
are released by other tasks.
withPermits(1)(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(const connection: SqliteConnectionconst connection: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
connection))
const const transactionAcquirer: Effect.Effect<
SqliteConnection,
never,
never
>
const transactionAcquirer: {
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;
}
transactionAcquirer = import EffectEffect.const uninterruptibleMask: <A, E, R>(
f: (
restore: <AX, EX, RX>(
effect: Effect<AX, EX, RX>
) => Effect<AX, EX, RX>
) => Effect<A, E, R>
) => Effect<A, E, R>
Disables interruption and provides a restore function to restore the
interruptible state within the effect.
Example (Restoring interruption in protected regions)
import { Console, Effect } from "effect"
const program = Effect.uninterruptibleMask((restore) =>
Effect.gen(function*() {
yield* Console.log("Uninterruptible phase...")
yield* Effect.sleep("1 second")
// Restore interruptibility for this part
yield* restore(
Effect.gen(function*() {
yield* Console.log("Interruptible phase...")
yield* Effect.sleep("2 seconds")
})
)
yield* Console.log("Back to uninterruptible")
})
)
uninterruptibleMask((restore: <AX, EX, RX>(
effect: Effect<AX, EX, RX>
) => Effect<AX, EX, RX>
restore) => {
const const fiber: Fiber.Fiber<any, any>const fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber = import FiberFiber.const getCurrent: () =>
| Fiber<any, any>
| undefined
Returns the current fiber if called from within a fiber context,
otherwise returns undefined.
When to use
Use when you need low-level runtime integrations that need access to the currently
executing fiber.
Gotchas
This is a synchronous accessor, not an Effect. It returns undefined outside
an active fiber runtime context.
Example (Getting the current fiber)
import { Effect, Fiber } from "effect"
const program = Effect.gen(function*() {
const current = Fiber.getCurrent()
if (current) {
console.log(`Current fiber ID: ${current.id}`)
}
})
getCurrent()!
const const scope: Scope.Scopeconst scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope = import ContextContext.const getUnsafe: {
<S, I>(service: Key<I, S>): <Services>(
self: Context<Services>
) => S
<Services, S, I>(
self: Context<Services>,
services: Key<I, S>
): S
}
Gets the service for a key, throwing if an absent non-reference key cannot be
resolved.
When to use
Use when you need to read a service from a context whose type does not prove
the service is present.
Details
If the key is a Context.Reference and no override is stored in the
context, its cached default value is returned. For absent non-reference keys,
this function throws a runtime error.
Example (Getting services unsafely)
import { Context } from "effect"
import * as assert from "node:assert"
const Port = Context.Service<{ PORT: number }>("Port")
const Timeout = Context.Service<{ TIMEOUT: number }>("Timeout")
const context = Context.make(Port, { PORT: 8080 })
assert.deepStrictEqual(Context.getUnsafe(context, Port), { PORT: 8080 })
assert.throws(() => Context.getUnsafe(context, Timeout))
getUnsafe(const fiber: Fiber.Fiber<any, any>const fiber: {
id: number;
currentOpCount: number;
getRef: <A>(ref: Context.Reference<A>) => A;
context: Context.Context<never>;
setContext: (context: Context.Context<never>) => void;
currentScheduler: Scheduler;
currentDispatcher: SchedulerDispatcher;
currentSpan: AnySpan | undefined;
currentLogLevel: LogLevel;
minimumLogLevel: LogLevel;
currentStackFrame: StackFrame | undefined;
maxOpsBeforeYield: number;
currentPreventYield: boolean;
addObserver: (cb: (exit: Exit<A, E>) => void) => () => void;
interruptUnsafe: (fiberId?: number | undefined, annotations?: Context.Context<never> | undefined) => void;
pollUnsafe: () => Exit<A, E> | 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; <…;
}
fiber.Fiber<any, any>.context: Context.Context<never>(property) Fiber<any, any>.context: {
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;
}
context, import ScopeScope.const Scope: Context.Service<Scope, Scope>const Scope: {
key: string;
Service: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
};
of: (this: void, self: Scope.Scope) => Scope.Scope;
context: (self: Scope.Scope) => Context.Context<Scope.Scope>;
use: (f: (service: Scope.Scope) => Effect.Effect<A, E, R>) => Effect.Effect<A, E, Scope.Scope | R>;
useSync: (f: (service: Scope.Scope) => A) => Effect.Effect<A, never, Scope.Scope>;
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;
}
A Scope represents a context where resources can be acquired and
automatically cleaned up when the scope is closed. Scopes can use
either sequential or parallel finalization strategies.
Example (Managing scoped resources)
import { Effect, Exit, Scope } from "effect"
const program = Effect.gen(function*() {
const scope = yield* Scope.make("sequential")
// Scope has a strategy and state
console.log(scope.strategy) // "sequential"
console.log(scope.state._tag) // "Open"
// Close the scope
yield* Scope.close(scope, Exit.void)
console.log(scope.state._tag) // "Closed"
})
Service tag for the active resource lifetime.
When to use
Use to access the active lifetime when registering finalizers or sharing
resources with the surrounding scope.
Example (Accessing the scope service)
import { Effect, Scope } from "effect"
const program = Effect.gen(function*() {
// Access the scope from the context
const scope = yield* Scope.Scope
// Use the scope for resource management
yield* Scope.addFinalizer(scope, Effect.log("Cleanup"))
})
// Provide a scope to the program
const scoped = Effect.scoped(program)
Scope)
return import EffectEffect.const as: {
<B>(value: B): <A, E, R>(
self: Effect<A, E, R>
) => Effect<B, E, R>
<A, E, R, B>(
self: Effect<A, E, R>,
value: B
): Effect<B, E, R>
}
Replaces the value inside an effect with a constant value.
When to use
Use to replace a successful value with a constant while preserving failures
and requirements.
Details
as allows you to ignore the original value inside an effect and
replace it with a new constant value.
Example (Replacing a success value)
import { Effect, pipe } from "effect"
// Replaces the value 5 with the constant "new value"
const program = pipe(Effect.succeed(5), Effect.as("new value"))
Effect.runPromise(program).then(console.log)
// Output: "new value"
as(
import EffectEffect.const tap: {
<A, B, E2, R2>(
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E | E2, R | R2>
<B, E2, R2>(f: Effect<B, E2, R2>): <A, E, R>(
self: Effect<A, E, R>
) => Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect<A, E, R>,
f: (a: NoInfer<A>) => Effect<B, E2, R2>
): Effect<A, E | E2, R | R2>
<A, E, R, B, E2, R2>(
self: Effect<A, E, R>,
f: Effect<B, E2, R2>
): Effect<A, E | E2, R | R2>
}
Runs a side effect with the result of an effect without changing the original
value.
When to use
Use when you need to run an effectful observation, such as logging or
tracking, while passing the original success value to the next step.
Details
tap works similarly to flatMap, but it ignores the result of the function
passed to it. The value from the previous effect remains available for the
next part of the chain. Note that if the side effect fails, the entire chain
will fail too.
Example (Logging a step in a pipeline)
import { Console, Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const finalAmount = pipe(
fetchTransactionAmount,
// Log the fetched transaction amount
Effect.tap((amount) => Console.log(`Apply a discount to: ${amount}`)),
// `amount` is still available!
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output:
// Apply a discount to: 100
// 95
tap(
restore: <AX, EX, RX>(
effect: Effect<AX, EX, RX>
) => Effect<AX, EX, RX>
restore(const semaphore: Semaphore.Semaphoreconst semaphore: {
resize: (this: Semaphore, permits: number) => Effect.Effect<void>;
withPermits: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermit: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermitsIfAvailable: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>;
take: (this: Semaphore, permits: number) => Effect.Effect<number>;
release: (this: Semaphore, permits: number) => Effect.Effect<number>;
releaseAll: Effect.Effect<number>;
}
semaphore.Semaphore.take(this: Semaphore, permits: number): Effect.Effect<number>Acquires the specified number of permits and returns the resulting
available permits, suspending the task if they are not yet available.
Concurrent pending take calls are processed in a first-in, first-out manner.
When to use
Use to manually acquire permits for lower-level coordination protocols.
take(1)),
() => 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(const scope: Scope.Scopeconst scope: {
strategy: "sequential" | "parallel";
state: State.Open | State.Closed | State.Empty;
}
scope, const semaphore: Semaphore.Semaphoreconst semaphore: {
resize: (this: Semaphore, permits: number) => Effect.Effect<void>;
withPermits: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermit: <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
withPermitsIfAvailable: (this: Semaphore, permits: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>;
take: (this: Semaphore, permits: number) => Effect.Effect<number>;
release: (this: Semaphore, permits: number) => Effect.Effect<number>;
releaseAll: Effect.Effect<number>;
}
semaphore.Semaphore.release(this: Semaphore, permits: number): Effect.Effect<number>Releases the specified number of permits and returns the resulting
available permits.
When to use
Use to manually return permits acquired by a lower-level coordination
protocol.
release(1))
),
const connection: SqliteConnectionconst connection: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
connection
)
})
return var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.assign<SqliteClient, {
"~@effect/sql-sqlite-node/SqliteClient": TypeId;
config: SqliteClientConfig;
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError, never>;
loadExtension: (path: string) => Effect.Effect<void, SqlError, never>;
}>(target: SqliteClient, source: {
"~@effect/sql-sqlite-node/SqliteClient": TypeId;
config: SqliteClientConfig;
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError, never>;
loadExtension: (path: string) => Effect.Effect<void, SqlError, never>;
}): SqliteClient & {
"~@effect/sql-sqlite-node/SqliteClient": TypeId;
config: SqliteClientConfig;
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError, never>;
loadExtension: (path: string) => Effect.Effect<void, SqlError, never>;
} (+3 overloads)
Copy the values of all of the enumerable own properties from one or more source objects to a
target object. Returns the target object.
assign(
(yield* import ClientClient.const make: (
options: Client.SqlClient.MakeOptions
) => Effect.Effect<
Client.SqlClient,
never,
Reactivity.Reactivity
>
Constructs a SqlClient from connection acquirers, a compiler, transaction
commands, tracing attributes, optional row transforms, and reactive query
integration.
make({
SqlClient.MakeOptions.acquirer: Effect.Effect<SqliteConnection, never, never>(property) SqlClient.MakeOptions.acquirer: {
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;
}
acquirer,
SqlClient.MakeOptions.compiler: Statement.Compiler(property) SqlClient.MakeOptions.compiler: {
dialect: Dialect;
compile: (statement: Fragment, withoutTransform: boolean) => readonly [sql: string, params: ReadonlyArray<unknown>];
withoutTransform: this;
}
compiler,
SqlClient.MakeOptions.transactionAcquirer?: Effect.Effect<SqliteConnection, never, never>(property) SqlClient.MakeOptions.transactionAcquirer?: {
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;
}
transactionAcquirer,
SqlClient.MakeOptions.spanAttributes: readonly (readonly [string, unknown])[]spanAttributes: [
...(options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.spanAttributes?: Record<string, unknown> | undefinedspanAttributes ? var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.entries<unknown>(o: {
[s: string]: unknown;
} | ArrayLike<unknown>): [string, unknown][] (+1 overload)
Returns an array of key/values of the enumerable own properties of an object
entries(options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options.SqliteClientConfig.spanAttributes?: Record<string, unknown>spanAttributes) : []),
[const ATTR_DB_SYSTEM_NAME: "db.system.name"ATTR_DB_SYSTEM_NAME, "sqlite"]
],
SqlClient.MakeOptions.transformRows?: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefinedtransformRows
})) as SqliteClient,
{
[const TypeId: TypeIdRuntime type identifier used to mark Node SqliteClient values.
Type-level identifier used to mark Node SqliteClient values.
TypeId]: const TypeId: TypeIdRuntime type identifier used to mark Node SqliteClient values.
Type-level identifier used to mark Node SqliteClient values.
TypeId as type TypeId =
"~@effect/sql-sqlite-node/SqliteClient"
Runtime type identifier used to mark Node SqliteClient values.
Type-level identifier used to mark Node SqliteClient values.
TypeId,
config: SqliteClientConfig(property) config: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
config: options: SqliteClientConfig(parameter) options: {
filename: string;
readonly: boolean | undefined;
prepareCacheSize: number | undefined;
prepareCacheTTL: Duration.Input | undefined;
disableWAL: boolean | undefined;
spanAttributes: Record<string, unknown> | undefined;
transformResultNames: ((str: string) => string) | undefined;
transformQueryNames: ((str: string) => string) | undefined;
}
options,
backup: (
destination: string
) => Effect.Effect<
BackupMetadata,
SqlError,
never
>
backup: (destination: stringdestination: string) => 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>
}
Chains effects to produce new Effect instances, useful for combining
operations that depend on previous results.
When to use
Use when you need to chain multiple effects, ensuring that each
step produces a new Effect while flattening any nested effects that may
occur.
Details
flatMap lets you sequence effects so that the result of one effect can be
used in the next step. It is similar to flatMap used with arrays but works
specifically with Effect instances, allowing you to avoid deeply nested
effect structures.
Since effects are immutable, flatMap always returns a new effect instead of
changing the original one.
Example (Choosing flatMap syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => Effect.succeed(n + 1)
const flatMappedWithPipe = pipe(myEffect, Effect.flatMap(transformation))
const flatMappedWithDataFirst = Effect.flatMap(myEffect, transformation)
const flatMappedWithMethod = myEffect.pipe(Effect.flatMap(transformation))
Example (Sequencing dependent effects)
import { Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Chaining the fetch and discount application using `flatMap`
const finalAmount = pipe(
fetchTransactionAmount,
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 95
flatMap(const acquirer: Effect.Effect<
SqliteConnection,
never,
never
>
const acquirer: {
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;
}
acquirer, (_: SqliteConnection(parameter) _: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
_) => _: SqliteConnection(parameter) _: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
_.SqliteConnection.backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>backup(destination: stringdestination)),
loadExtension: (
path: string
) => Effect.Effect<void, SqlError, never>
loadExtension: (path: stringpath: string) => 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>
}
Chains effects to produce new Effect instances, useful for combining
operations that depend on previous results.
When to use
Use when you need to chain multiple effects, ensuring that each
step produces a new Effect while flattening any nested effects that may
occur.
Details
flatMap lets you sequence effects so that the result of one effect can be
used in the next step. It is similar to flatMap used with arrays but works
specifically with Effect instances, allowing you to avoid deeply nested
effect structures.
Since effects are immutable, flatMap always returns a new effect instead of
changing the original one.
Example (Choosing flatMap syntax variants)
import { Effect, pipe } from "effect"
const myEffect = Effect.succeed(1)
const transformation = (n: number) => Effect.succeed(n + 1)
const flatMappedWithPipe = pipe(myEffect, Effect.flatMap(transformation))
const flatMappedWithDataFirst = Effect.flatMap(myEffect, transformation)
const flatMappedWithMethod = myEffect.pipe(Effect.flatMap(transformation))
Example (Sequencing dependent effects)
import { Data, Effect, pipe } from "effect"
class DiscountRateError extends Data.TaggedError("DiscountRateError")<{}> {}
// Function to apply a discount safely to a transaction amount
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, DiscountRateError> =>
discountRate === 0
? Effect.fail(new DiscountRateError())
: Effect.succeed(total - (total * discountRate) / 100)
// Simulated asynchronous task to fetch a transaction amount from database
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
// Chaining the fetch and discount application using `flatMap`
const finalAmount = pipe(
fetchTransactionAmount,
Effect.flatMap((amount) => applyDiscount(amount, 5))
)
Effect.runPromise(finalAmount).then(console.log)
// Output: 95
flatMap(const acquirer: Effect.Effect<
SqliteConnection,
never,
never
>
const acquirer: {
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;
}
acquirer, (_: SqliteConnection(parameter) _: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
_) => _: SqliteConnection(parameter) _: {
backup: (destination: string) => Effect.Effect<BackupMetadata, SqlError>;
loadExtension: (path: string) => Effect.Effect<void, SqlError>;
execute: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
executeRaw: (sql: string, params: ReadonlyArray<unknown>) => Effect<unknown, SqlError>;
executeStream: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Stream<any, SqlError>;
executeValues: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeValuesUnprepared: (sql: string, params: ReadonlyArray<unknown>) => Effect<ReadonlyArray<ReadonlyArray<unknown>>, SqlError>;
executeUnprepared: (sql: string, params: ReadonlyArray<unknown>, transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined) => Effect<ReadonlyArray<any>, SqlError>;
}
_.SqliteConnection.loadExtension: (path: string) => Effect.Effect<void, SqlError>loadExtension(path: stringpath))
}
)
})