declarationOrder
Definitions, in an order one file can declare them in: each after what it uses as it's initialized (a constant's value, a class it extends), as TypeScript wants it ("used before its declaration"), and otherwise as given. Each item is one or more definitions written together (a type and a value of one name); a cycle of such uses, which no order typechecks, is broken where it's come to.
import type { DefRecord } from "#codebase/tcmts/core/types"; export function declarationOrder<T>(items: T[], recsOf: (item: T) => DefRecord[]): T[] { const of = new Map<string, T>(); for (const it of items) for (const r of recsOf(it)) of.set(r.hash, it); const out: T[] = []; const seen = new Set<T>(); const visit = (it: T) => { if (seen.has(it)) return; seen.add(it); for (const r of recsOf(it)) for (const d of r.deps) { const dep = d.strict && d.ref.startsWith("#") ? of.get(d.ref.slice(1)) : undefined; if (dep !== undefined && dep !== it) visit(dep); } out.push(it); }; items.forEach(visit); return out; }