import { TrackedComputedSubject } from "../tracked-computed-subject"; interface ComputedProperty { subject: TrackedComputedSubject; } type ComputedPropertyList = { [K in keyof T]: ComputedProperty; }; const ComputedPropertyListKey = "_computedProperties"; const getComputedPropertyList = (obj: T) => ((obj as any)[ComputedPropertyListKey] = (obj as any)[ComputedPropertyListKey] || {}) as ComputedPropertyList; export const getOrSetupComputedProperty = (obj: T, name: K, getter: () => T[K]): TrackedComputedSubject => { const list = getComputedPropertyList(obj); const existing = list[name]; if (!existing) { const subject = new TrackedComputedSubject(getter.bind(obj)); list[name] = { subject }; } return list[name].subject; }; export const getComputedProperty = (obj: T, name: K): TrackedComputedSubject => { const list = getComputedPropertyList(obj); if (!list[name]) { obj[name]; // Has not been initialized, so initialized it now // Lazy initialization seems to be the correct step here? See the long comment in tracked-property.ts //console.info("computed initialized lazily via getComputedProperty", obj, name, list); //throw new Error("Property accessed before initialized: " + name); } return list[name].subject; };