Skip to content

TxRef.ts

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.

Since v4.0.0



Reads the current value of the TxRef.

When to use

Use to read the current value of a TxRef.

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))
console.log(value) // 42
})

Signature

declare const get: <A>(self: TxRef<A>) => Effect.Effect<A>

Source

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.

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])
console.log(result) // 0 (the return value: current * 2)
console.log(yield* TxRef.get(counter)) // 1 (the new value: current + 1)
})

Signature

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

Source

Since v2.0.0

Sets the value of the TxRef.

When to use

Use to replace the value of a TxRef.

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))
console.log(yield* TxRef.get(counter)) // 100
})

Signature

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

Source

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.

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))
console.log(yield* TxRef.get(counter)) // 20
})

Signature

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

Source

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.

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")
})
)
console.log(yield* TxRef.get(counter)) // 42
console.log(yield* TxRef.get(name)) // "Bob"
})

Signature

declare const make: <A>(initial: A) => Effect.Effect<TxRef<A>, never, never>

Source

Since v2.0.0

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.

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
console.log(counter.value) // 0
console.log(config.value) // { timeout: 5000, retries: 3 }

Signature

declare const makeUnsafe: <A>(initial: A) => TxRef<A>

Source

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.

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)
})
)
const final = yield* TxRef.get(ref)
console.log(final) // 1
})

Signature

export interface TxRef<in out A> extends Pipeable {
readonly [TypeId]: typeof TypeId
version: number
pending: Map<unknown, () => void>
value: A
}

Source

Since v4.0.0