I'm working on a Angular 7 app that uses the NGRX store. We have a lot of entities, and almost each one has a dedicated list view. I wanted to try out generics with NGRX store, so I would not need to write almost identical selectors, actions, reducers etc. I started with actions and created a function that would return me a set of them, but I cannot get it to work.
// For type safety
enum AddTypeNames {
ADD_REQUEST = 'AddRequestAction',
ADD_SUCCESS = 'AddSuccessAction',
ADD_FAILURE = 'AddFailureAction',
}
// Creates an object literal with a string key and Action as the value
function createAddActions<T>(featureName: string): { [key in AddTypeNames]: Action } {
class AddRequestAction implements Action {
readonly type = `[${featureName}] Add request`;
constructor(payload: { entity: T }) { }
}
class AddSuccessAction implements Action {
readonly type = `[${featureName}] Add success`;
constructor(payload: { entity: T }) { }
}
class AddFailureAction implements Action {
readonly type = `[${featureName}] Add error`;
constructor(payload: { error: HttpErrorResponse }) { }
}
return {
AddRequestAction,
AddSuccessAction,
AddFailureAction,
};
}
But it's showing an error in the editor saying:
(property) AddRequestAction: Action
Property 'type' is missing in type 'typeof AddRequestAction' but required in type 'Action'.ts(2741)
I've no idea what this error really means, as clearly I do have the type in the class... Am I even doing this the right way? What would I need to do to create actions with generic types? Is it actually considered a good practice to use generics as much as possible?
Compilation error existing because you declared that createAddActions
will return dict od Action { [key in AddTypeNames]: Action }
. But this syntax means object of instances of class Action, not a classes.
So, you told TS that your return object values contains attribute 'type', your classes has not static attribute type
.
If you want to declare that result of functions is object with classes (not instances of it use this syntax: { new (...args): Action }
.
So:
function createAddActions<T>(featureName: string): { [key in AddTypeNames]: { new (...args): Action } } {
will not throws compilation error.