docs / Language

Track Declarations

The &[] sugar for creating reactive cells: auto-tracked bindings, raw-cell bindings, and how the compiler rewrites reads and writes.

The `&[]` track-declaration syntax is Vesk's sugar for creating reactive cells — it combines cell creation with variable binding in a single statement.

Syntax

app/components/Counter.vsk
									
										let &[count] = track(0);           // count is the auto-tracked cell
const &[items] = track<string[]>([]);  // works with const too
let &[total, rawTotal] = track(0);     // rawTotal is the raw Tracked<number>
									
								
  • The first name is the reactive value — reads inside effects or component bodies subscribe, writes schedule an update automatically.
  • The optional second name is the raw cell object, used with `untrack()`, `peek()` or when passing the cell around.
  • Each `&[]` creates its own cell; there is no multi-cell shorthand.
  • `&[]` can only appear at the top level of a component body, or inside a `block()`/`effect()`/`root()` call.

How the compiler rewrites it

User code Compiled output
count get(count)
count = 5 set(count, 5)
count++ set(count, get(count) + 1)
count + 1 get(count) + 1

You never call `get()` or `set()` manually when using `&[]` bindings — the compiler inserts them for you. The `&[]` binding atom is parsed with `lazy: true` and becomes a `TrackDecl` IR node.

Derived cells

app/components/Price.vsk
										
											component Price(props: { qty: number, unit: number }) {
  let &[total] = derived(() => props.qty * props.unit);
  <p>Total: {total}</p>
}
										
									

`total` is read-only — writing to it throws. The function re-runs whenever a tracked dependency read inside it changes.