Forger Help

Circular References

Self-referencing types — trees, linked lists, graphs — cannot be forged to infinity. Forger nests them up to the configured circular depth and stops with null.

The circularDepth argument

The second argument of create controls how deep a self-reference may go; the default is 1:

interface Node { name: string; child?: Node; } const node = Forger.create<Node>()!; // { // name: 'E^BU%tPqQ{', // child: { name: 'L%/M;$,:NJ', child: null } // depth 1: one nested level // }

A higher depth nests further before cutting off:

const deep = Forger.create<Node>({}, 2)!; // { // name: '…', // child: { // name: '…', // child: { name: '…', child: null } // depth 2: two nested levels // } // }

What the depth counts

The depth applies per type: every time the transformer enters a type it has already visited, it checks the counter against circularDepth. Distinct types referencing each other in a cycle (A → B → A) share the same mechanics.

The depth is resolved per call: passing circularDepth to one create call never affects other calls, even those compiled after it in the same file.

Properties that are not part of a cycle are never truncated — the depth limit protects only against infinite recursion.

Choosing a depth

Depth

Use when

1

The test touches node.child but never deeper (default)

23

The algorithm under test walks a fixed number of levels

higher

Rarely needed — consider building the chain with createWith instead

For deep structures, combining generation with pinning is often clearer:

const leaf = Forger.create<TreeNode>()!; const root = Forger.createWith<TreeNode>() .with(t => t.children = [leaf, leaf]) .result()!;

null at the cutoff

The level after the last allowed one is null (not undefined), for optional and required references alike. Tests that walk generated trees should treat null as the leaf marker.

08 September 2026