type LazyResolver = T | Promise | (() => (T | Promise)); export class LazyObject { constructor(factory: LazyResolver) { if (factory instanceof Promise) { this._factory = () => factory; } else if (typeof factory === 'function') { this._factory = factory; } else { this._resolvedValue = factory; } } static from(value: Lazy) { if (value instanceof LazyObject) return value; return new LazyObject(value); } get resolved() { return this._resolved; } get value() { return this._resolvedValue; } private _factory; private _resolved = false; private _resolvedValue: T | null = null; private _resolvingPromise: Promise | null = null; async resolve() { if (this._resolved) return this._resolvedValue; if (this._resolvingPromise) { return await this._resolvingPromise; } const value = this._factory(); if (value instanceof Promise) { this._resolvingPromise = value; this._resolvedValue = await this._resolvingPromise; } this._resolved = true; this._resolvedHandlers.forEach(handler => handler(this._resolvedValue)); this._resolvedHandlers = []; return this._resolvedValue; } private _resolvedHandlers: ((value: T) => void)[] = []; onResolve(callback: (value: T) => void) { if (this._resolved) { callback(this._resolvedValue); } else { this._resolvedHandlers.push(callback); } } } export type Lazy = LazyObject | LazyResolver;