I am trying to build an Angular 2/ngrx application based on the example app found at https://github.com/ngrx/example-app/ . I am exporting action types as a discriminated union
export const ActionTypes = {
QUERY: type('[Games] Query'),
QUERY_COMPLETE: type('[Games] Query Complete'),
INVALIDATE: type('[Games] Invalidate'),
SELECT: type('[Games] Select'),
LOAD_NEXT_PAGE: type('[Games] Load Next Page'),
LOAD_NEXT_PAGE_COMPLETE: type('[Games] Load Next Page Complete'),
};
export class QueryAction implements Action {
type = ActionTypes.QUERY;
constructor(public payload: string) {}
}
export class QueryCompleteAction implements Action {
type = ActionTypes.QUERY_COMPLETE;
constructor(public payload: Game[]) {}
}
export class LoadNextPageCompleteAction implements Action {
type = ActionTypes.LOAD_NEXT_PAGE_COMPLETE;
constructor(public payload: Game[]) {}
}
export class LoadNextPageAction implements Action {
type = ActionTypes.LOAD_NEXT_PAGE;
constructor() {}
}
export class InvalidateAction implements Action {
type = ActionTypes.INVALIDATE;
constructor(){}
}
export class SelectAction implements Action {
type = ActionTypes.SELECT;
constructor(public payload: number) {}
}
export type Actions = QueryAction | QueryCompleteAction | InvalidateAction | SelectAction | LoadNextPageAction | LoadNextPageCompleteAction;
And passing these to the reducer function, discriminating based on the type property as follows:
export function reducer(state = initialState, action: game.Actions): State {
switch (action.type) {
case game.ActionTypes.LOAD_NEXT_PAGE:
case game.ActionTypes.QUERY: {
return Object.assign({}, state, {loading: true});
}
case game.ActionTypes.QUERY_COMPLETE: {
return {
games: action.payload,
offset: action.payload.length,
loading: false,
selectedGameId: null
}
}
case game.ActionTypes.LOAD_NEXT_PAGE_COMPLETE: {
return {
games: [...state.games, ...action.payload],
offset: state.offset + action.payload.length,
loading: false,
selectedGameId: state.selectedGameId
}
}
case game.ActionTypes.SELECT: {
return Object.assign({}, state, {selectedGameId: action.payload});
}
default: {
return state;
}
}
}
This fails to compile with the error (among other errors)
Type 'string | number | Game[]' is not assignable to type 'Game[]'.
Type 'string' is not assignable to type 'Game[]'.
Property 'length' does not exist on type 'string | number | Game[]'.
Property 'length' does not exist on type 'number'
Am I doing something wrong or not understanding how discriminated unions work? My understanding was that the switch statement should narrow down the possible types of action.payload so it is guaranteed to be the correct type. It seems to be comparing to the types of all of the members of the union, instead of only the one with the matched type.
The project is using Typescript v2.1.6
gameactions. Make sure its pointing at the the correct actions file. - rtn