API / @aihu/signals

@aihu/signals

runtime core

Tiny reactive primitives — the reactive core of aihu.

Small (≤ 2 kB gz) reactive primitives — the foundation layer for aihu’s arbor renderer. One read shape (the signal tuple), one underlying cell. Sync semantics, lazy computed, explicit batch. No proxies, no scheduler queue, no global tick.

exports
8
functions
5
types
3
size
≤ 2 kB
01

signal

function
function signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>

Create a reactive cell. Returns a readonly [read, write] tuple — the single read shape the whole runtime is built on.

ParameterTypeDescription
initialTThe initial value held by the cell.
options?SignalOptions<T>Optional equals comparator to suppress no-op notifications.

ReturnsSignal<T> — a readonly [Read<T>, Write<T>] tuple.

import { signal, effect } from '@aihu/signals'

const [count, setCount] = signal(0)
effect(() => console.log('count =', count()))
setCount(1)             // logs "count = 1"
setCount((n) => n + 10) // logs "count = 11"
02

computed

function
function computed<T>(fn: () => T, options?: ComputedOptions<T>): Read<T> & { dispose(): void }

A lazily-evaluated derived value. Recomputes only when read after a dependency changed; memoized by Object.is (or a custom equals).

ParameterTypeDescription
fn() => TPure computation over other reactive reads.
options?ComputedOptions<T>Optional equals comparator for memoization.

ReturnsRead<T> & { dispose(): void }

import { signal, computed } from '@aihu/signals'

const [n, setN] = signal(2)
const doubled = computed(() => n() * 2)
doubled() // 4
03

effect

function
function effect(fn: EffectFn): Dispose

Run a side effect and re-run it whenever any signal read inside it changes. Returns a Dispose to stop tracking.

ParameterTypeDescription
fnEffectFnThe reactive side effect to run and track.

ReturnsDispose — call to tear the effect down.

import { signal, effect } from '@aihu/signals'

const [ok, setOk] = signal(true)
const stop = effect(() => document.title = ok() ? 'on' : 'off')
stop() // stop reacting
04

batch

function
function batch<T>(fn: () => T): T

Coalesce multiple writes so dependents recompute once, after the batch commits — the explicit alternative to a global scheduler tick.

ParameterTypeDescription
fn() => TWork that performs several writes.

ReturnsT — the value returned by fn.

import { signal, batch, effect } from '@aihu/signals'

const [a, setA] = signal(1)
const [b, setB] = signal(2)
effect(() => console.log(a() + b()))
batch(() => { setA(10); setB(20) }) // logs once: 30
05

untrack

function
function untrack<T>(fn: () => T): T

Read signals without subscribing the current effect/computed to them.

ParameterTypeDescription
fn() => TA read that must not create a dependency.

ReturnsT — the value returned by fn.

06

Signal

type
type Signal<T> = readonly [Read<T>, Write<T>]

The tuple returned by signal — a reader and a writer over one cell.

07

Read

type
type Read<T> = () => T

A tracked getter. Calling it inside an effect/computed subscribes to the cell.

08

Write

type
type Write<T> = <U extends T>(next: (Exclude<U, AnyFn> & T) | ((prev: T) => U)) => void

A setter accepting either a next value or an updater function of the previous value.