Type interference for the DS

This commit is contained in:
FinnStutzenstein 2018-09-10 08:57:53 +02:00
parent 548e720795
commit dc0c92253d
10 changed files with 39 additions and 32 deletions

View File

@ -1,4 +1,4 @@
import { ModelConstructor } from '../../shared/models/base.model';
import { ModelConstructor, BaseModel } from '../../shared/models/base.model';
/**
* Registeres the mapping of collection strings <--> actual types. Every Model should register itself here.
@ -8,14 +8,14 @@ export class CollectionStringModelMapperService {
* Mapps collection strings to model constructors. Accessed by {@method registerCollectionElement} and
* {@method getCollectionStringType}.
*/
private static collectionStringsTypeMapping: { [collectionString: string]: ModelConstructor } = {};
private static collectionStringsTypeMapping: { [collectionString: string]: ModelConstructor<BaseModel> } = {};
/**
* Registers the type to the collection string
* @param collectionString
* @param type
*/
public static registerCollectionElement(collectionString: string, type: ModelConstructor) {
public static registerCollectionElement(collectionString: string, type: ModelConstructor<BaseModel>) {
CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString] = type;
}
@ -23,7 +23,7 @@ export class CollectionStringModelMapperService {
* Returns the constructor of the requested collection or undefined, if it is not registered.
* @param collectionString the requested collection
*/
public static getModelConstructor(collectionString: string): ModelConstructor {
public static getModelConstructor(collectionString: string): ModelConstructor<BaseModel> {
return CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString];
}
@ -31,7 +31,7 @@ export class CollectionStringModelMapperService {
* Returns the collection string of a given ModelConstructor or undefined, if it is not registered.
* @param ctor
*/
public static getCollectionString(ctor: ModelConstructor): string {
public static getCollectionString(ctor: ModelConstructor<BaseModel>): string {
return Object.keys(CollectionStringModelMapperService.collectionStringsTypeMapping).find(
(collectionString: string) => {
return ctor === CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString];

View File

@ -182,7 +182,7 @@ export class DataStoreService {
});
}
private getCollectionString(collectionType: ModelConstructor | string): string {
private getCollectionString<T extends BaseModel>(collectionType: ModelConstructor<T> | string): string {
if (typeof collectionType === 'string') {
return collectionType;
} else {
@ -197,10 +197,10 @@ export class DataStoreService {
* @param ids One ID of the BaseModel
* @return The given BaseModel-subclass instance
* @example: this.DS.get(User, 1)
* @example: this.DS.get('core/countdown', 2)
* @example: this.DS.get<Countdown>('core/countdown', 2)
*/
public get<T extends BaseModel>(collectionType: ModelConstructor | string, id: number): T {
const collectionString = this.getCollectionString(collectionType);
public get<T extends BaseModel>(collectionType: ModelConstructor<T> | string, id: number): T {
const collectionString = this.getCollectionString<T>(collectionType);
const collection: ModelCollection = this.modelStore[collectionString];
if (!collection) {
@ -211,14 +211,16 @@ export class DataStoreService {
}
/**
* Read multiple ID's from dataStore
* Read multiple ID's from dataStore.
*
* @param collectionType The desired BaseModel or collectionString to be read from the dataStore
* @param ids Multiple IDs as a list of IDs of BaseModel
* @return The BaseModel-list corresponding to the given ID(s)
* @example: this.DS.get(User, [1,2,3,4,5])
* @example: this.DS.getMany(User, [1,2,3,4,5])
* @example: this.DS.getMany<User>('users/user', [1,2,3,4,5])
*/
public getMany<T extends BaseModel>(collectionType: ModelConstructor | string, ids: number[]): T[] {
const collectionString = this.getCollectionString(collectionType);
public getMany<T extends BaseModel>(collectionType: ModelConstructor<T> | string, ids: number[]): T[] {
const collectionString = this.getCollectionString<T>(collectionType);
const collection: ModelCollection = this.modelStore[collectionString];
if (!collection) {
@ -234,12 +236,14 @@ export class DataStoreService {
/**
* Get all models of the given collection from the DataStore.
*
* @param collectionType The desired BaseModel or collectionString to be read from the dataStore
* @return The BaseModel-list of all instances of T
* @example: this.DS.get(User)
* @example: this.DS.getAll(User)
* @example: this.DS.getAll<User>('users/user')
*/
public getAll<T extends BaseModel>(collectionType: ModelConstructor | string): T[] {
const collectionString = this.getCollectionString(collectionType);
public getAll<T extends BaseModel>(collectionType: ModelConstructor<T> | string): T[] {
const collectionString = this.getCollectionString<T>(collectionType);
const collection: ModelCollection = this.modelStore[collectionString];
if (!collection) {
@ -258,14 +262,15 @@ export class DataStoreService {
* @example this.DS.filter<User>(User, myUser => myUser.first_name === "Max")
*/
public filter<T extends BaseModel>(
collectionType: ModelConstructor | string,
collectionType: ModelConstructor<T> | string,
callback: (model: T) => boolean
): T[] {
return this.getAll<T>(collectionType).filter(callback);
}
/**
* Add one or multiple models to dataStore
* Add one or multiple models to dataStore.
*
* @param ...models The model(s) that shall be add use spread operator ("...")
* @example this.DS.add(new User(1))
* @example this.DS.add((new User(2), new User(3)))
@ -296,7 +301,8 @@ export class DataStoreService {
}
/**
* removes one or multiple models from dataStore
* removes one or multiple models from dataStore.
*
* @param Type The desired BaseModel type to be read from the dataStore
* @param ...ids An or multiple IDs or a list of IDs of BaseModels. use spread operator ("...") for arrays
* @example this.DS.remove(User, myUser.id, 3, 4)

View File

@ -140,7 +140,7 @@ export class OperatorService extends OpenSlidesComponent {
private updatePermissions(): void {
this.permissions = [];
if (!this.user) {
const defaultGroup = this.DS.get('users/group', 1) as Group;
const defaultGroup = this.DS.get<Group>('users/group', 1);
if (defaultGroup && defaultGroup.permissions instanceof Array) {
this.permissions = defaultGroup.permissions;
}

View File

@ -2,8 +2,8 @@ import { OpenSlidesComponent } from 'app/openslides.component';
import { Deserializable } from './deserializable.model';
import { CollectionStringModelMapperService } from '../../core/services/collectionStringModelMapper.service';
export interface ModelConstructor {
new (...args: any[]): BaseModel;
export interface ModelConstructor<T extends BaseModel> {
new (...args: any[]): T;
}
/**

View File

@ -1,4 +1,5 @@
import { BaseModel } from '../base.model';
import { Item } from '../agenda/item';
/**
* Representation of a motion block.
@ -19,7 +20,7 @@ export class MotionBlock extends BaseModel {
}
public getAgenda(): BaseModel | BaseModel[] {
return this.DS.get('agenda/item', this.agenda_item_id);
return this.DS.get<Item>('agenda/item', this.agenda_item_id);
}
}

View File

@ -76,7 +76,7 @@ export class Motion extends BaseModel {
*/
public initDataStoreValues() {
// check the containing Workflows in DataStore
const allWorkflows = this.DS.getAll<Workflow>(Workflow);
const allWorkflows = this.DS.getAll(Workflow);
allWorkflows.forEach(localWorkflow => {
if (localWorkflow.isStateContained(this.state_id)) {
this.workflow = localWorkflow as Workflow;

View File

@ -34,7 +34,7 @@ export class User extends BaseModel {
}
public get groups(): Group[] {
return this.DS.getMany<Group>(Group, this.groups_id);
return this.DS.getMany(Group, this.groups_id);
}
public get full_name(): string {

View File

@ -53,7 +53,7 @@ export class CategoryListComponent extends BaseComponent implements OnInit {
*/
public ngOnInit() {
super.setTitle('Category');
this.categoryArray = this.DS.getAll<Category>(Category);
this.categoryArray = this.DS.getAll(Category);
this.dataSource = new MatTableDataSource(this.categoryArray);
this.dataSource.sort = this.sort;
@ -61,7 +61,7 @@ export class CategoryListComponent extends BaseComponent implements OnInit {
// The alternative approach is to put the observable as DataSource to the table
this.DS.changeObservable.subscribe(newModel => {
if (newModel instanceof Category) {
this.categoryArray = this.DS.getAll<Category>(Category);
this.categoryArray = this.DS.getAll(Category);
this.dataSource.data = this.categoryArray;
}
});

View File

@ -88,7 +88,7 @@ export class MotionDetailComponent extends BaseComponent implements OnInit {
// load existing motion
this.route.params.subscribe(params => {
// has the motion of the DataStore was initialized before.
this.motion = this.DS.get(Motion, params.id) as Motion;
this.motion = this.DS.get(Motion, params.id);
// Observe motion to get the motion in the parameter and also get the changes
this.DS.changeObservable.subscribe(newModel => {
@ -165,7 +165,7 @@ export class MotionDetailComponent extends BaseComponent implements OnInit {
* return all Categories.
*/
public getMotionCategories(): Category[] {
return this.DS.getAll<Category>(Category);
return this.DS.getAll(Category);
}
/**

View File

@ -93,8 +93,8 @@ export class MotionListComponent extends BaseComponent implements OnInit {
*/
public ngOnInit() {
super.setTitle('Motions');
this.workflowArray = this.DS.getAll<Workflow>(Workflow);
this.motionArray = this.DS.getAll<Motion>(Motion);
this.workflowArray = this.DS.getAll(Workflow);
this.motionArray = this.DS.getAll(Motion);
this.dataSource = new MatTableDataSource(this.motionArray);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
@ -103,7 +103,7 @@ export class MotionListComponent extends BaseComponent implements OnInit {
// The alternative approach is to put the observable as DataSource to the table
this.DS.changeObservable.subscribe(newModel => {
if (newModel instanceof Motion) {
this.motionArray = this.DS.getAll<Motion>(Motion);
this.motionArray = this.DS.getAll(Motion);
this.dataSource.data = this.motionArray;
}
});