export type Constructor = new (...args: any[]) => T; export type RegisterFn = (unknown: any) => Item; export class Registry< Item, Items extends Record = Record, Fn extends RegisterFn = RegisterFn > { private is_set: boolean = false; private items: Items = {} as Items; constructor(private registerFn?: Fn) {} set>(items: Actual) { if (this.is_set) { throw new Error("Registry is already set"); } this.items = items as unknown as Items; this.is_set = true; return this as unknown as Registry; } add(name: string, item: Item) { this.items[name as keyof Items] = item as Items[keyof Items]; return this; } register(name: string, specific: Parameters[0]) { if (this.registerFn) { const item = this.registerFn(specific); this.items[name as keyof Items] = item as Items[keyof Items]; return this; } return this.add(name, specific); } get(name: Name): Items[Name] { return this.items[name]; } has(name: keyof Items): boolean { return name in this.items; } all() { return this.items; } }