| name | mongez-reinforcements-lazy |
| description | Memoised deferred values via lazy() from @mongez/reinforcements — the primary tool for breaking ES-module circular imports and deferring expensive computation until first use.
|
Lazy
Memoised deferred values. The flagship utility of the package — the unique tool for breaking ES-module circular imports.
import { lazy, isLazy, type Lazy, type LazyAsync } from "@mongez/reinforcements";
lazy(producer)
lazy<T>(producer: () => T): Lazy<T>
type Lazy<T> = {
resolve(): T;
reset(): void;
isResolved(): boolean;
peek(): T | undefined;
};
The producer is not invoked until the first resolve(). The result is then memoised.
const config = lazy(() => loadHeavyConfig());
config.resolve();
config.resolve();
config.reset();
config.resolve();
config.peek();
config.isResolved();
Why it exists: circular imports
JavaScript closures capture variable bindings, not values. When Module A imports Module B which imports Module A, the value that A wants from B might not be defined yet at module-init time. lazy() defers the reference resolution to call time.
const service = lazy(() => Service);
export function handler() {
return service.resolve().run();
}
lazy.async(producer)
lazy.async<T>(producer: () => Promise<T>): LazyAsync<T>
type LazyAsync<T> = {
resolve(): Promise<T>;
reset(): void;
isResolved(): boolean;
peek(): Promise<T> | undefined;
};
Same shape as lazy, but the cached value is a Promise<T>.
const user = lazy.async(() => fetch("/api/me").then(r => r.json()));
await user.resolve();
await user.resolve();
user.reset();
await user.resolve();
lazy.from(value)
lazy.from<T>(value: T): Lazy<T>
Pre-resolved lazy — for tests or for API symmetry where a Lazy<T> is expected but the value is already known.
const ref = lazy.from(42);
ref.resolve();
ref.isResolved();
ref.reset();
isLazy(value)
isLazy<T = unknown>(value: unknown): value is Lazy<T>
Type guard. Returns true for both lazy() and lazy.async() results.
if (isLazy<number>(value)) {
value.resolve();
}
Idioms
Resetting on config reload:
const cachedConfig = lazy(() => parseConfigFile());
watchConfigFile(() => {
cachedConfig.reset();
});
export function getSetting(key: string) {
return cachedConfig.resolve()[key];
}
Disambiguating "not yet resolved" from "resolved to undefined":
const maybe = lazy(() => undefined);
maybe.isResolved();
maybe.peek();
maybe.resolve();
maybe.isResolved();
maybe.peek();
Error retry: producers that throw are not memoised; the next resolve() re-invokes the producer.