export interface ICollection { items: T[]; totalCount: number; toArray(): T[]; } export class Collection implements ICollection { protected _items: Map; protected _totalCount: number | undefined = undefined; protected _totalCountIsProvided = false; get totalCount(): number { if (this._totalCountIsProvided) { return Number(this._totalCount); } return Array.from(this._items.values()).reduce( (total, item) => (item !== undefined ? total + 1 : total), 0 ); } get items(): T[] { return Array.from(this._items.values()).filter((item) => item); } constructor(initialValues?: T[], totalCount?: number) { this._items = new Map( initialValues ? initialValues.map((value: any, index: number) => [index, value] as [number, T]) : [] ); this._totalCountIsProvided = typeof totalCount === "number"; if (this._totalCountIsProvided) { this._totalCount = Number(totalCount); } } private incTotalCount() { if (this._totalCountIsProvided) { this._totalCount = Number(this._totalCount) + 1; } } private decTotalCount() { if (this._totalCountIsProvided) { this._totalCount = Number(this._totalCount) - 1; } } private resetTotalCount() { this._totalCount = 0; } /*public static createEmpty() { return new Collection([]); } public static create(initialValues: any[], totalCount?: number) { return new Collection(initialValues, totalCount); }*/ public reset() { this._items.clear(); this.resetTotalCount(); } public addItem(item: T) { this._items.set(this._items.size, item); this.incTotalCount(); } public replaceItem(index: number, item: T) { this._items.set(index, item); } public removeByIndex(index: number) { this._items.delete(index); // <--- this._items.set(index, undefined); this.decTotalCount(); } public addCollection(collection: ICollection) { if (collection) { collection.items.forEach((item: T) => { this.addItem(item); }); } } public find(predicate: (value: T, index: number, obj: T[]) => unknown): T | undefined { return Array.from(this._items.values()).find(predicate); } public toArray(): T[] { return this.items; } public toString(): string { return this.items .map((item) => (item !== undefined ? JSON.stringify(item) : undefined)) .toString(); } public toStringArray(): string[] { return Array.from(this._items.values(), (element) => JSON.stringify(element)).filter( (element) => element.length > 0 ); } }