# RefSubject

A `RefSubject` is a mutable reference that can be observed as an Fx.
It combines the capabilities of a `Ref` (get/set/update) with a `Subject` (subscribe).

## Signatures

```ts
export interface RefSubject<A, E = never, R = never> extends Computed<A, E, R>, Subject.Subject<A, E, R> {
    readonly [RefSubjectTypeId]: RefSubjectTypeId;
    readonly updates: <B, E2, R2>(f: (ref: GetSetDelete<A, E, R>) => Effect.Effect<B, E2, R2>) => Effect.Effect<B, E | E2, R | R2>;
    readonly interrupt: Effect.Effect<void, never, R>;
}
```

```ts
export declare namespace RefSubject {
    type Any = RefSubject<any, any, any> | RefSubject<any, any> | RefSubject<any, never, any> | RefSubject<any>;
    interface Service<Self, Id extends string, A, E> extends RefSubject<A, E, Self> {
        readonly id: Id;
        readonly service: Context.Service<Self, RefSubject<A, E>>;
        readonly make: <R = never>(value: A | Effect.Effect<A, E, R> | Fx<A, E, R>, options?: RefSubjectOptions<A> & {
            readonly skip?: number;
            readonly take?: number;
        }) => Layer.Layer<Self, never, Exclude<R, Scope.Scope>>;
        readonly layer: <E2, R2>(make: Effect.Effect<RefSubject<A, E>, E2, R2 | Scope.Scope>) => Layer.Layer<Self, E2, Exclude<R2, Scope.Scope>>;
    }
    interface Class<Self, Id extends string, A, E> extends RefSubject.Service<Self, Id, A, E> {
        new (): RefSubject.Service<Self, Id, A, E>;
    }
}
```

## Why

Unifies synchronized mutable state, Effectful current reads, and Fx pushes so the same state can
be tested and consumed without a renderer.

## Ownership and lifetime

RefSubject is a contract and performs no acquisition. Implementations retain the errors,
services, interruption, and Scope requirements expressed by its members.

## Property: [[computed:[RefSubjectTypeId]]]

Carries the runtime marker recognized by `isRefSubject`.

## Property: [[computed:[RefSubjectTypeId]]]: Why

Marks the value as a writable RefSubject for runtime guards while retaining its Computed and
Subject capabilities.

## Property: [[computed:[RefSubjectTypeId]]]: Ownership and lifetime

This declaration performs no acquisition and retains no resources. Implementations preserve
source errors, services, and lifetime.

## Property: interrupt

Interrupts the RefSubject, stopping all subscriptions and cleaning up resources.

## Property: interrupt: Why

Interrupts the RefSubject, stopping all subscriptions and cleaning up resources.

## Property: interrupt: Ownership and lifetime

Running this Effect returns `void`: it resets pending initialization, closes the RefSubject's
private Scope, interrupts its initializer fiber, and interrupts its Subject. It cannot fail;
`R` supplies services captured by the RefSubject's internal lifetime.

## Property: updates

Runs an effect that can modify the RefSubject transactionally.
All operations within the transaction are atomic and serialized.

## Property: updates: Why

Runs an effect that can modify the RefSubject transactionally. All operations within the
transaction are atomic and serialized. The transition is serialized at the RefSubject rather
than coordinated by callers or UI components.

## Property: updates: Ownership and lifetime

Running updates performs one serialized subject transition and returns the committed value.
It acquires no resource and preserves source failures and services.

## Examples

```ts
import { Effect } from "effect"
import { Fx, RefSubject } from "@typed/fx"

// Create a RefSubject with an initial value
const program = Effect.scoped(Effect.gen(function* () {
  const count = yield* RefSubject.make(0)

  // Get the current value
  const current = yield* count
  console.log(current) // 0

  // Update the value
  yield* RefSubject.set(count, 5)
  const updated = yield* count
  console.log(updated) // 5

  // Use as an Fx to observe changes
  yield* Effect.forkScoped(Fx.observe(
    count,
    (value) => Effect.sync(() => console.log("Count changed:", value))
  ))

  // Increment
  yield* RefSubject.increment(count)
  // Output: "Count changed: 6"
}))
```

```ts
import { Effect } from "effect"
import * as RefSubject from "@typed/fx/RefSubject"

const program = Effect.gen(function* () {
  const ref = yield* RefSubject.make(0)

  // Later, clean up
  yield* ref.interrupt
})
```

```ts
import { Effect } from "effect"
import * as RefSubject from "@typed/fx/RefSubject"

const program = Effect.gen(function* () {
  const balance = yield* RefSubject.make(100)

  // Transfer money atomically
  yield* balance.updates((ref) =>
    Effect.gen(function* () {
      const current = yield* ref.get
      if (current >= 50) {
        yield* ref.set(current - 50)
        return "Transfer successful"
      }
      return "Insufficient funds"
    })
  )
})
```
