The TC39 Signals core
The primitives you've seen — createSignal, createMemo, createEffect — are built on a small,
standards-shaped core: an implementation of the TC39 Signals proposal. You rarely need it
directly, but it's there when you want the lowest-level API or to build your own reactive
abstractions.
Signal.State
A writable signal — the equivalent of createSignal:
import { Signal } from '@fluixi/reactive/signal';
const count = new Signal.State(0);
count.get(); // 0
count.set(1);
count.get(); // 1
It's equality-gated like createSignal; pass { equals } to customize.
Signal.Computed
A lazy, cached derived signal — the equivalent of createMemo:
const doubled = new Signal.Computed(() => count.get() * 2);
doubled.get(); // recomputes only when count changes
A computed runs only when read, and only recomputes when a dependency it read actually changed — the same glitch-free, lazy behavior as a memo.
Signal.subtle.Watcher
State and Computed are pull-based: nothing runs on its own. To react eagerly — the basis of
effects — use a Watcher. Its callback fires when a watched signal might have changed; it must not
read signals itself, only schedule work:
let queued = false;
const w = new Signal.subtle.Watcher(() => {
if (queued) return;
queued = true;
queueMicrotask(() => {
queued = false;
for (const node of w.getPending()) node.get(); // re-read to settle
w.watch(); // re-arm
});
});
w.watch(doubled);
count.set(2); // schedules the watcher
getPending() returns the watched signals that may have changed; re-reading them settles the graph,
and watch() re-arms the watcher. This is exactly how createEffect is implemented under the hood.
subtle utilities
The Signal.subtle namespace also exposes untrack(fn) (read without subscribing),
currentComputed() (the computed currently evaluating, if any), and hasSinks(signal) (whether
anything observes a signal).
Why this matters
Because the core follows the TC39 model, your reactive state is interoperable and the graph is
introspectable — which is precisely what powers the live dependency graph in the
Playground and @fluixi/devtools.
The everyday API (createSignal and friends) is almost always what you want — but now you know
what's underneath it.