Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

TxRef

Transactional references for coordinating mutable state with Effect transactions. A TxRef stores a current value, but reads and writes inside Effect.tx are recorded in a transaction journal and committed together only when the outermost transaction succeeds.

This is the basic building block behind the other transactional collections in Effect. The module provides effectful and unsafe constructors plus the core operations for reading, setting, updating, and modifying a transactional value while returning a separate result.

7 exports Since v2.0.0 Source

Combinators

Since v2.0.0

Reads the current value of the TxRef.

When to use

Use to read the current value of a TxRef.

Signature

declare function get<A>(self: TxRef<A>): Effect<A>

Example Reading transactional references

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const counter = yield* TxRef.make(42)
// Read the value within a transaction
const value = yield* Effect.tx(
TxRef.get(counter)
)
return value
})
await Effect.runPromise(program) // => 42
Since v2.0.0

Modifies the value of the TxRef using the provided function.

When to use

Use to update a TxRef and return a computed result from the same transaction step.

Signature

declare const modify: {
<A, R>(f: (current: NoInfer<A>) => [returnValue: R, newValue: A]): (self: TxRef<A>) => Effect<R>;
<A, R>(self: TxRef<A>, f: (current: A) => [returnValue: R, newValue: A]): Effect<R>;
}

Example Modifying transactional references

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const counter = yield* TxRef.make(0)
// Modify and return both old and new value
const result = yield* TxRef.modify(counter, (current) => [current * 2, current + 1])
return [result, yield* TxRef.get(counter)]
})
await Effect.runPromise(program) // => [0, 1]
Since v2.0.0

Sets the value of the TxRef.

When to use

Use to replace the value of a TxRef.

Signature

declare const set: {
<A>(value: A): (self: TxRef<A>) => Effect<void>;
<A>(self: TxRef<A>, value: A): Effect<void>;
}

Example Setting transactional references

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const counter = yield* TxRef.make(0)
// Set a new value within a transaction
yield* Effect.tx(
TxRef.set(counter, 100)
)
return yield* TxRef.get(counter)
})
await Effect.runPromise(program) // => 100
Since v2.0.0

Updates the value of the TxRef using the provided function.

When to use

Use to transform a TxRef when no result value is needed.

Signature

declare const update: {
<A>(f: (current: NoInfer<A>) => A): (self: TxRef<A>) => Effect<void>;
<A>(self: TxRef<A>, f: (current: A) => A): Effect<void>;
}

Example Updating transactional references

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
const counter = yield* TxRef.make(10)
// Update the value using a function
yield* Effect.tx(
TxRef.update(counter, (current) => current * 2)
)
return yield* TxRef.get(counter)
})
await Effect.runPromise(program) // => 20

Constructors

Since v2.0.0

Creates a new TxRef with the specified initial value.

When to use

Use to create a TxRef inside an Effect workflow.

Signature

declare function make<A>(initial: A): Effect<TxRef<A>, never, never>

Example Creating transactional references

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
// Create a transactional reference with initial value
const counter = yield* TxRef.make(0)
const name = yield* TxRef.make("Alice")
// Use in transactions
yield* Effect.tx(Effect.gen(function*() {
yield* TxRef.set(counter, 42)
yield* TxRef.set(name, "Bob")
}))
return [yield* TxRef.get(counter), yield* TxRef.get(name)]
})
await Effect.runPromise(program) // => [42, "Bob"]

Creates a new TxRef synchronously with the specified initial value.

When to use

Use to construct a TxRef synchronously when it must be created outside an Effect workflow.

Signature

declare function makeUnsafe<A>(initial: A): TxRef<A>

Example Creating transactional references unsafely

import { TxRef } from "effect"
// Create a TxRef synchronously (unsafe - use make instead in Effect contexts)
const counter = TxRef.makeUnsafe(0)
const config = TxRef.makeUnsafe({ timeout: 5000, retries: 3 })
// These are now ready to use in transactions
counter.value // => 0
config.value // => { timeout: 5000, retries: 3 }

Models

TxRef

interface
Since v4.0.0

TxRef is a transactional value, it can be read and modified within the body of a transaction.

When to use

Use to store mutable state that must be read and modified inside Effect transactions.

Details

Accessed values are tracked by the transaction in order to detect conflicts and in order to track changes, a transaction will retry whenever a conflict is detected or whenever the transaction explicitely calls to Effect.txRetry and any of the accessed TxRef values change.

Signature

interface TxRef<in out A> extends Pipeable {
readonly "~effect/TxRef": "~effect/TxRef";
pending: Map<unknown, () => void>;
value: A;
version: number;
}

Example Using a transactional reference

import { Effect, TxRef } from "effect"
const program = Effect.gen(function*() {
// Create a transactional reference
const ref: TxRef.TxRef<number> = yield* TxRef.make(0)
// Use within a transaction
yield* Effect.tx(Effect.gen(function*() {
const current = yield* TxRef.get(ref)
yield* TxRef.set(ref, current + 1)
}))
return yield* TxRef.get(ref)
})
await Effect.runPromise(program) // => 1