1+ import type ResourceInterface from './interfaces/ResourceInterface'
2+ import type CollectionInterface from './interfaces/CollectionInterface'
3+ import type { Link , StoreDataCollection } from '@/interfaces/StoreData'
4+
15import { isEntityReference } from './halHelpers'
26import LoadingCollection from './LoadingCollection'
3- import ResourceInterface from './interfaces/ResourceInterface'
4- import CollectionInterface from './interfaces/CollectionInterface'
5- import { Link } from './interfaces/StoreData'
67import Resource from './Resource'
78
89/**
910 * Filter out items that are marked as deleting (eager removal)
1011 */
11- function filterDeleting ( array : Array < ResourceInterface > ) : Array < ResourceInterface > {
12+ function filterDeleting < T extends ResourceInterface > ( array : Array < T > ) : Array < T > {
1213 return array . filter ( entry => ! entry . _meta . deleting )
1314}
1415
15- class Collection extends Resource {
16+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17+ class Collection < ItemType extends ResourceInterface , ResourceType extends CollectionInterface < ItemType , ResourceType > = any > extends Resource < ResourceType , StoreDataCollection < ResourceType > > implements CollectionInterface < ItemType , ResourceType > {
1618 /**
1719 * Get items excluding ones marked as 'deleting' (eager remove)
1820 * The items property should always be a getter, in order to make the call to mapArrayOfEntityReferences
1921 * lazy, since that potentially fetches a large number of entities from the API.
2022 */
21- public get items ( ) : Array < ResourceInterface > {
22- return filterDeleting ( this . _mapArrayOfEntityReferences ( this . _storeData . items ) )
23+ public get items ( ) : Array < ItemType > {
24+ return filterDeleting < ItemType > ( this . _mapArrayOfEntityReferences ( this . _storeData . items ) )
2325 }
2426
2527 /**
2628 * Get all items including ones marked as 'deleting' (lazy remove)
2729 */
28- public get allItems ( ) : Array < ResourceInterface > {
30+ public get allItems ( ) : Array < ItemType > {
2931 return this . _mapArrayOfEntityReferences ( this . _storeData . items )
3032 }
3133
3234 /**
3335 * Returns a promise that resolves to the collection object, once all items have been loaded
3436 */
35- public $loadItems ( ) : Promise < CollectionInterface > {
37+ public $loadItems ( ) : Promise < this > {
3638 return this . _itemLoader ( this . _storeData . items )
3739 }
3840
3941 /**
4042 * Returns a promise that resolves to the collection object, once all items have been loaded
4143 */
42- private _itemLoader ( array : Array < Link > ) : Promise < CollectionInterface > {
44+ private _itemLoader ( array : Array < ItemType > ) : Promise < this > {
4345 if ( ! this . _containsUnknownEntityReference ( array ) ) {
44- return Promise . resolve ( this as unknown as CollectionInterface ) // we know that this object must be of type CollectionInterface
46+ return Promise . resolve ( this ) // we know that this object must be of type CollectionInterface
4547 }
4648
4749 // eager loading of 'fetchAllUri' (e.g. parent for embedded collections)
4850 if ( this . config . avoidNPlusOneRequests ) {
49- return this . apiActions . reload ( this as unknown as CollectionInterface ) as Promise < CollectionInterface > // we know that reload resolves to a type CollectionInterface
51+ return this . apiActions . reload < ItemType > ( this ) as unknown as Promise < this > // we know that reload resolves to a type CollectionInterface
5052
5153 // no eager loading: replace each reference (Link) with a Resource (ResourceInterface)
5254 } else {
5355 const arrayWithReplacedReferences = this . _replaceEntityReferences ( array )
5456
5557 return Promise . all (
5658 arrayWithReplacedReferences . map ( entry => entry . _meta . load )
57- ) . then ( ( ) => this as unknown as CollectionInterface ) // we know that this object must be of type CollectionInterface
59+ ) . then ( ( ) => this ) // we know that this object must be of type CollectionInterface
5860 }
5961 }
6062
@@ -68,7 +70,7 @@ class Collection extends Resource {
6870 * @returns array the new array with replaced items, or a LoadingCollection if any of the array
6971 * elements is still loading.
7072 */
71- private _mapArrayOfEntityReferences ( array : Array < Link > ) : Array < ResourceInterface > {
73+ private _mapArrayOfEntityReferences ( array : Array < ItemType > ) : Array < ItemType > {
7274 if ( ! this . _containsUnknownEntityReference ( array ) ) {
7375 return this . _replaceEntityReferences ( array )
7476 }
@@ -77,27 +79,26 @@ class Collection extends Resource {
7779
7880 // eager loading of 'fetchAllUri' (e.g. parent for embedded collections)
7981 if ( this . config . avoidNPlusOneRequests ) {
80- return LoadingCollection . create ( itemsLoaded )
82+ return LoadingCollection . create < ItemType > ( itemsLoaded )
8183
8284 // no eager loading: replace each reference (Link) with a Resource (ResourceInterface)
8385 } else {
84- return LoadingCollection . create ( itemsLoaded , this . _replaceEntityReferences ( array ) )
86+ return LoadingCollection . create < ItemType > ( itemsLoaded , this . _replaceEntityReferences ( array ) )
8587 }
8688 }
8789
8890 /**
8991 * Replace each item in array with a proper Resource (or LoadingResource)
9092 */
91- private _replaceEntityReferences ( array : Array < Link > ) : Array < ResourceInterface > {
92- return array
93- . filter ( entry => isEntityReference ( entry ) )
94- . map ( entry => this . apiActions . get ( entry . href ) )
93+ private _replaceEntityReferences ( array : Array < ItemType > ) : Array < ItemType > {
94+ const links = array . filter ( entry => isEntityReference ( entry ) ) as unknown as Link [ ]
95+ return links . map ( entry => this . apiActions . get < ItemType > ( entry . href ) as ItemType )
9596 }
9697
9798 /**
9899 * Returns true if any of the items within 'array' is not yet known to the API (meaning it has never been loaded)
99100 */
100- private _containsUnknownEntityReference ( array : Array < Link > ) : boolean {
101+ private _containsUnknownEntityReference ( array : Array < ItemType > ) : boolean {
101102 return array . some ( entry => isEntityReference ( entry ) && this . apiActions . isUnknown ( entry . href ) )
102103 }
103104}
0 commit comments