MutableRef
Stores synchronous mutable state in a small reference object.
A MutableRef<A> stores one current value and exposes it through .current.
Unlike Ref, its operations are synchronous and update the same object in
place. This module includes pipeable helpers for reading, setting, comparing,
and updating the value, plus numeric increment/decrement helpers and a
boolean toggle helper.
Constructors
Creates a new MutableRef with the specified initial value.
When to use
Use to create a synchronous MutableRef initialized with a value.
Signature
declare function make<T>(value: T): MutableRef<T>Example
(Creating mutable refs)
import { MutableRef } from "effect"
// Create a counter referenceconst counter = MutableRef.make(0)
MutableRef.get(counter) // => 0
// Create a configuration referenceconst config = MutableRef.make({ debug: false, timeout: 5000 })
MutableRef.get(config) // => { debug: false, timeout: 5000 }
// Create a string referenceconst status = MutableRef.make("idle")MutableRef.set(status, "running")
MutableRef.get(status) // => "running"Getters
Gets the current value of the MutableRef.
When to use
Use to read the current MutableRef value without mutating it.
Signature
declare function get<T>(self: MutableRef<T>): TExample
(Reading current values)
import { MutableRef } from "effect"
const ref = MutableRef.make("hello")
MutableRef.get(ref) // => "hello"
MutableRef.set(ref, "world")
MutableRef.get(ref) // => "world"
// Reading complex objectsconst config = MutableRef.make({ port: 3000, host: "localhost" })const currentConfig = MutableRef.get(config)
currentConfig // => { port: 3000, host: "localhost" }
// Multiple reads return the same valueconst value1 = MutableRef.get(ref)const value2 = MutableRef.get(ref)
value1 === value2 // => trueModels
MutableRef interface
A synchronous mutable reference that stores a current value.
When to use
Use to keep local mutable state in a stable, pipeable reference.
Details
Read or write the value directly through .current, or use the MutableRef
helpers for pipeable updates such as get, set, update, and
compareAndSet. All operations mutate the same reference in place.
Signature
interface MutableRef<out T> extends Pipeable, Inspectable { readonly "~effect/MutableRef": "~effect/MutableRef"; current: T;}Example
(Creating and updating refs)
import { MutableRef } from "effect"
// Create a mutable referenceconst ref: MutableRef.MutableRef<number> = MutableRef.make(42)
// Read the current valueref.current // => 42MutableRef.get(ref) // => 42
// Update the valueref.current = 100
MutableRef.get(ref) // => 100
// Use with complex typesinterface Config { timeout: number retries: number}
const config: MutableRef.MutableRef<Config> = MutableRef.make({ timeout: 5000, retries: 3})
// Update through the interfaceconfig.current = { timeout: 10000, retries: 5 }
config.current // => { timeout: 10000, retries: 5 }Mutations
compareAndSet
Sets the value to newValue atomically if the current value equals oldValue. Returns true if the value was updated, false otherwise. Uses Effect's Equal interface for value comparison.
When to use
Use to replace a MutableRef value only when the current value still matches
an expected value.
Signature
declare const compareAndSet: { <T>(oldValue: T, newValue: T): (self: MutableRef<T>) => boolean; <T>(self: MutableRef<T>, oldValue: T, newValue: T): boolean;}Example
(Comparing and setting values)
import { MutableRef } from "effect"
const ref = MutableRef.make("initial")
// Successful compare and setconst updated = MutableRef.compareAndSet(ref, "initial", "updated")
updated // => trueMutableRef.get(ref) // => "updated"
// Failed compare and set (value doesn't match)const failed = MutableRef.compareAndSet(ref, "initial", "failed")
failed // => falseMutableRef.get(ref) // => "updated"
// Thread-safe counter incrementconst counter = MutableRef.make(5)let current: numberdo { current = MutableRef.get(counter)} while (!MutableRef.compareAndSet(counter, current, current + 1))
MutableRef.get(counter) // => 6
// Pipe-able versionconst casUpdate = MutableRef.compareAndSet("updated", "final")
casUpdate(ref) // => trueMutableRef.get(ref) // => "final"Decrements a numeric MutableRef by 1 and returns the reference.
When to use
Use when you need an in-place MutableRef decrement that returns the same
MutableRef.
Signature
declare function decrement(self: MutableRef<number>): MutableRef<number>Example
(Decrementing numeric refs)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Decrement the counterMutableRef.decrement(counter)
MutableRef.get(counter) // => 4
// Chain operationsMutableRef.decrement(counter)MutableRef.decrement(counter)
MutableRef.get(counter) // => 2
// Useful for countdown scenariosconst countdown = MutableRef.make(10)while (MutableRef.get(countdown) > 0) { MutableRef.decrement(countdown)}
MutableRef.get(countdown) // => 0decrementAndGet
Decrements a numeric MutableRef by 1 and returns the new value.
When to use
Use to decrement a numeric MutableRef and immediately read the updated
value.
Signature
declare function decrementAndGet(self: MutableRef<number>): numberExample
(Decrementing and reading refs)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Decrement and get the new valueconst newValue = MutableRef.decrementAndGet(counter)
newValue // => 4MutableRef.get(counter) // => 4
// Use in expressionsconst lives = MutableRef.make(3)const message = `Lives remaining: ${MutableRef.decrementAndGet(lives)}`
message // => "Lives remaining: 2"
// Conditional logic based on decremented valueconst attempts = MutableRef.make(3)let retries = 0while (MutableRef.decrementAndGet(attempts) >= 0) { retries += 1}
retries // => 3MutableRef.get(attempts) // => -1getAndDecrement
Decrements a numeric MutableRef by 1 and returns the previous value.
When to use
Use to read the current numeric MutableRef value before decrementing it.
Signature
declare function getAndDecrement(self: MutableRef<number>): numberExample
(Reading before decrementing)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Get current value and then decrementconst previousValue = MutableRef.getAndDecrement(counter)
previousValue // => 5MutableRef.get(counter) // => 4
// Useful for processing where you need the original valueconst itemsLeft = MutableRef.make(10)const processedItems: Array<number> = []while (MutableRef.get(itemsLeft) > 0) { const currentItem = MutableRef.getAndDecrement(itemsLeft) processedItems.push(currentItem)}
processedItems // => [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]MutableRef.get(itemsLeft) // => 0
// Post-decrement semantics (like i-- in other languages)const index = MutableRef.make(3)const currentIndex = MutableRef.getAndDecrement(index)const nextIndex = MutableRef.get(index)
currentIndex // => 3nextIndex // => 2getAndIncrement
Increments a numeric MutableRef by 1 and returns the previous value.
When to use
Use to read the current numeric MutableRef value before incrementing it.
Signature
declare function getAndIncrement(self: MutableRef<number>): numberExample
(Reading before incrementing)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Get current value and then incrementconst previousValue = MutableRef.getAndIncrement(counter)
previousValue // => 5MutableRef.get(counter) // => 6
// Useful for ID generationconst idGenerator = MutableRef.make(0)const getId = () => MutableRef.getAndIncrement(idGenerator)const ids = [getId(), getId(), getId()]
ids // => [0, 1, 2]
// Post-increment semantics (like i++ in other languages)const position = MutableRef.make(0)const currentPos = MutableRef.getAndIncrement(position)const nextPos = MutableRef.get(position)
currentPos // => 0nextPos // => 1
// Useful for iteration countersconst iterations = MutableRef.make(0)const visited: Array<number> = []while (MutableRef.get(iterations) < 5) { const iteration = MutableRef.getAndIncrement(iterations) visited.push(iteration)}
visited // => [0, 1, 2, 3, 4]MutableRef.get(iterations) // => 5Sets the MutableRef to a new value and returns the previous value.
When to use
Use to replace the current MutableRef value while keeping the previous
value.
Signature
declare const getAndSet: { <T>(value: T): (self: MutableRef<T>) => T; <T>(self: MutableRef<T>, value: T): T;}Example
(Reading before setting)
import { MutableRef } from "effect"
const ref = MutableRef.make("old")
// Set new value and get the previous oneconst previous = MutableRef.getAndSet(ref, "new")
previous // => "old"MutableRef.get(ref) // => "new"
// Swapping valuesconst counter = MutableRef.make(5)const oldValue = MutableRef.getAndSet(counter, 10)const newValue = MutableRef.get(counter)
oldValue // => 5newValue // => 10
// Pipe-able versionconst setValue = MutableRef.getAndSet("final")const previousValue = setValue(ref)
previousValue // => "new"MutableRef.get(ref) // => "final"
// Useful for atomic swaps in algorithmsconst buffer = MutableRef.make<Array<string>>(["a", "b", "c"])const oldBuffer = MutableRef.getAndSet(buffer, [])
oldBuffer // => ["a", "b", "c"]MutableRef.get(buffer) // => []getAndUpdate
Updates the MutableRef with the result of applying a function to its current value, and returns the previous value.
When to use
Use to transform the current MutableRef value while keeping the previous
value.
Signature
declare const getAndUpdate: { <T>(f: (value: T) => T): (self: MutableRef<T>) => T; <T>(self: MutableRef<T>, f: (value: T) => T): T;}Example
(Reading before updating)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Increment and get the old valueconst oldValue = MutableRef.getAndUpdate(counter, (n) => n + 1)
oldValue // => 5MutableRef.get(counter) // => 6
// Double the value and get the previous oneconst previous = MutableRef.getAndUpdate(counter, (n) => n * 2)
previous // => 6MutableRef.get(counter) // => 12
// Transform string and get old valueconst message = MutableRef.make("hello")const oldMessage = MutableRef.getAndUpdate(message, (s) => s.toUpperCase())
oldMessage // => "hello"MutableRef.get(message) // => "HELLO"
// Pipe-able versionconst addOne = MutableRef.getAndUpdate((n: number) => n + 1)const result = addOne(counter)
result // => 12MutableRef.get(counter) // => 13
// Useful for implementing atomic operationsconst list = MutableRef.make<Array<number>>([1, 2, 3])const oldList = MutableRef.getAndUpdate(list, (arr) => [...arr, 4])
oldList // => [1, 2, 3]MutableRef.get(list) // => [1, 2, 3, 4]Increments a numeric MutableRef by 1 and returns the reference.
When to use
Use when you need an in-place MutableRef increment that returns the same
MutableRef.
Signature
declare function increment(self: MutableRef<number>): MutableRef<number>Example
(Incrementing numeric refs)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Increment the counterMutableRef.increment(counter)
MutableRef.get(counter) // => 6
// Chain operationsMutableRef.increment(counter)MutableRef.increment(counter)
MutableRef.get(counter) // => 8
// Useful for simple countingconst visits = MutableRef.make(0)MutableRef.increment(visits) // User visitedMutableRef.increment(visits) // Another visit
MutableRef.get(visits) // => 2
// Returns the reference for chainingconst result = MutableRef.increment(counter)
result === counter // => trueMutableRef.get(counter) // => 9incrementAndGet
Increments a numeric MutableRef by 1 and returns the new value.
When to use
Use to increment a numeric MutableRef and immediately read the updated
value.
Signature
declare function incrementAndGet(self: MutableRef<number>): numberExample
(Incrementing and reading refs)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Increment and get the new valueconst newValue = MutableRef.incrementAndGet(counter)
newValue // => 6MutableRef.get(counter) // => 6
// Use in expressionsconst score = MutableRef.make(100)const message = `New score: ${MutableRef.incrementAndGet(score)}`
message // => "New score: 101"
// Pre-increment semantics (like ++i in other languages)const level = MutableRef.make(0)const nextLevel = MutableRef.incrementAndGet(level)
nextLevel // => 1
// Conditional logic based on incremented valueconst attempts = MutableRef.make(0)const tooManyAttempts = MutableRef.incrementAndGet(attempts) > 3
tooManyAttempts // => falseMutableRef.get(attempts) // => 1Sets the MutableRef to a new value and returns the reference.
When to use
Use when you need an in-place MutableRef replacement that returns the same
MutableRef.
Signature
declare const set: { <T>(value: T): (self: MutableRef<T>) => MutableRef<T>; <T>(self: MutableRef<T>, value: T): MutableRef<T>;}Example
(Setting values)
import { MutableRef } from "effect"
const ref = MutableRef.make("initial")
// Set a new valueMutableRef.set(ref, "updated")
MutableRef.get(ref) // => "updated"
// Chain set operations (since it returns the ref)const result = MutableRef.set(ref, "final")
result === ref // => trueMutableRef.get(ref) // => "final"
// Set complex objectsconst config = MutableRef.make({ debug: false, verbose: false })MutableRef.set(config, { debug: true, verbose: true })
MutableRef.get(config) // => { debug: true, verbose: true }
// Pipe-able versionconst setValue = MutableRef.set("new value")setValue(ref)
MutableRef.get(ref) // => "new value"
// Useful for state managementconst state = MutableRef.make<"idle" | "loading" | "success" | "error">("idle")MutableRef.set(state, "loading")// ... perform async operationMutableRef.set(state, "success")
MutableRef.get(state) // => "success"Sets the MutableRef to a new value and returns the new value.
When to use
Use to replace the current MutableRef value and immediately read the
replacement.
Signature
declare const setAndGet: { <T>(value: T): (self: MutableRef<T>) => T; <T>(self: MutableRef<T>, value: T): T;}Example
(Setting and reading values)
import { MutableRef } from "effect"
const ref = MutableRef.make("old")
// Set and get the new valueconst newValue = MutableRef.setAndGet(ref, "new")
newValue // => "new"MutableRef.get(ref) // => "new"
// Useful for assignments that need the valueconst counter = MutableRef.make(0)const currentValue = MutableRef.setAndGet(counter, 42)
currentValue // => 42
// Pipe-able versionconst setValue = MutableRef.setAndGet("final")const result = setValue(ref)
result // => "final"
// Difference from set: returns value instead of referenceconst ref1 = MutableRef.make(1)const returnedRef = MutableRef.set(ref1, 2) // Returns MutableRefconst returnedValue = MutableRef.setAndGet(ref1, 3) // Returns value
returnedRef === ref1 // => truereturnedValue // => 3MutableRef.get(ref1) // => 3Switches a boolean MutableRef between true and false, then returns the
reference.
When to use
Use when you need an in-place boolean MutableRef toggle that returns the
same MutableRef.
Signature
declare function toggle(self: MutableRef<boolean>): MutableRef<boolean>Example
(Toggling boolean refs)
import { MutableRef } from "effect"
const flag = MutableRef.make(false)
// Toggle the flagMutableRef.toggle(flag)
MutableRef.get(flag) // => true
// Toggle againMutableRef.toggle(flag)
MutableRef.get(flag) // => false
// Useful for state switchesconst isVisible = MutableRef.make(true)MutableRef.toggle(isVisible) // Hide
MutableRef.get(isVisible) // => false
// Toggle button implementationconst darkMode = MutableRef.make(false)const toggleDarkMode = () => { MutableRef.toggle(darkMode) return MutableRef.get(darkMode) ? "ON" : "OFF"}
toggleDarkMode() // => "ON"toggleDarkMode() // => "OFF"
// Returns the reference for chainingconst result = MutableRef.toggle(flag)
result === flag // => trueMutableRef.get(flag) // => trueUpdates the MutableRef with the result of applying a function to its current value, and returns the reference.
When to use
Use when you need an in-place MutableRef value transformation that returns
the same MutableRef.
Signature
declare const update: { <T>(f: (value: T) => T): (self: MutableRef<T>) => MutableRef<T>; <T>(self: MutableRef<T>, f: (value: T) => T): MutableRef<T>;}Example
(Updating values)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Increment the counterMutableRef.update(counter, (n) => n + 1)
MutableRef.get(counter) // => 6
// Chain updates (since it returns the ref)const result = MutableRef.update(counter, (n) => n * 2)
result === counter // => trueMutableRef.get(counter) // => 12
// Transform stringconst message = MutableRef.make("hello")MutableRef.update(message, (s) => s.toUpperCase())
MutableRef.get(message) // => "HELLO"
// Update complex objectsconst user = MutableRef.make({ name: "Alice", age: 30 })MutableRef.update(user, (u) => ({ ...u, age: u.age + 1 }))
MutableRef.get(user) // => { name: "Alice", age: 31 }
// Pipe-able versionconst double = MutableRef.update((n: number) => n * 2)double(counter)
MutableRef.get(counter) // => 24
// Array operationsconst list = MutableRef.make<Array<number>>([1, 2, 3])MutableRef.update(list, (arr) => [...arr, 4])
MutableRef.get(list) // => [1, 2, 3, 4]updateAndGet
Updates the MutableRef with the result of applying a function to its current value, and returns the new value.
When to use
Use to transform the current MutableRef value and immediately read the
updated value.
Signature
declare const updateAndGet: { <T>(f: (value: T) => T): (self: MutableRef<T>) => T; <T>(self: MutableRef<T>, f: (value: T) => T): T;}Example
(Updating and reading values)
import { MutableRef } from "effect"
const counter = MutableRef.make(5)
// Increment and get the new valueconst newValue = MutableRef.updateAndGet(counter, (n) => n + 1)
newValue // => 6MutableRef.get(counter) // => 6
// Double the value and get the resultconst doubled = MutableRef.updateAndGet(counter, (n) => n * 2)
doubled // => 12
// Transform string and get resultconst message = MutableRef.make("hello")const upperCase = MutableRef.updateAndGet(message, (s) => s.toUpperCase())
upperCase // => "HELLO"
// Pipe-able versionconst increment = MutableRef.updateAndGet((n: number) => n + 1)const result = increment(counter)
result // => 13
// Useful for calculations that need the resultconst score = MutableRef.make(100)const bonus = 50const newScore = MutableRef.updateAndGet(score, (s) => s + bonus)
newScore // => 150
// Array transformationsconst list = MutableRef.make<Array<number>>([1, 2, 3])const newList = MutableRef.updateAndGet(list, (arr) => arr.map((x) => x * 2))
newList // => [2, 4, 6]MutableRef.get(list) // => [2, 4, 6]