具有多个有效负载的@ngrx操作

时间:2017-08-02 15:43:22

标签: angular typescript redux ngrx

我正在使用Angular 4和@ngrx 4创建一个Web应用程序,我在配置强类型操作时遇到问题。

我是@ngrx的新手,我为我的行为创建了以下类:

export const ActionTypes = {
  LOAD_PRODUCT_TREE: 'load-product-tree',
  LOAD_PRODUCT_TREE_COMPLETE: 'load-product-tree-complete'
};

// Load product tree by Id.
export class LoadProductTreeAction implements Action {
  type = ActionTypes.LOAD_PRODUCT_TREE;
  constructor (public payload: number) { }
}

export class LoadProductTreeCompleteAction implements Action {
  type = ActionTypes.LOAD_PRODUCT_TREE_COMPLETE;
  constructor (public payload: Map<number, Node>) { }
}

export type Actions = LoadProductTreeAction | LoadProductTreeCompleteAction;

但是当我尝试在我的reducer中使用这些动作时:

export interface State {
  productTree: Map<number, Node>;
}

const initialState: State = {
  productTree: new Map<number, Node>()
};

export function productTreeReducer(state = initialState, action: productTreeOperations.Actions): State {

  switch (action.type) {
    case productTreeOperations.ActionTypes.LOAD_PRODUCT_TREE:
      return state;

    case productTreeOperations.ActionTypes.LOAD_PRODUCT_TREE_COMPLETE:
      return { productTree: action.payload };

    default:
      return state;
  }

}

我收到此错误:Type '{ productTree: number | Map<number, Node>; }' is not assignable to type 'State'. Types of property 'productTree' are incompatible. Type 'number | Map<number, Node>' is not assignable to type 'Map<number, Node>'. Type 'number' is not assignable to type 'Map<number, Node>'.在此行中:return { productTree: action.payload };

如何创建一组采用不同有效负载/参数的操作?

对于减速器中LOAD_PRODUCT_TREE动作的返回值,最佳做法是什么?我应该在从后端加载信息时返回当前状态,还是应该返回其他内容?

3 个答案:

答案 0 :(得分:4)

假设您正在使用框架的默认Action接口,请执行以下重构:

export const LOAD_PRODUCT_TREE = 'load-product-tree';
export const LOAD_PRODUCT_TREE_COMPLETE = 'load-product-tree-complete';

export class LoadProductTreeAction implements Action {
  readonly type = LOAD_PRODUCT_TREE;
  constructor (public payload: number) { }
}

export class LoadProductTreeCompleteAction implements Action {
  readonly type = LOAD_PRODUCT_TREE_COMPLETE;
  constructor (public payload: Map<number, Node>) { }
}

export type Actions = LoadProductTreeAction | LoadProductTreeCompleteAction;

export function productTreeReducer(state = initialState, action: productTreeOperations.Actions): State {

  switch (action.type) {
    case productTreeOperations.LOAD_PRODUCT_TREE:
      return state;

    case productTreeOperations.LOAD_PRODUCT_TREE_COMPLETE:
      return { productTree: action.payload };

    default:
      return state;
  }
}

我稍后会添加相应的解释,但基本上你希望typescript将type属性识别为单独的类型,而不是字符串。

答案 1 :(得分:0)

问题的关键是readonly关键字

您需要将操作类型设置为只读

答案 2 :(得分:-2)

我很难阅读你的代码并猜测它,但我认为你有

export class Action{
    type: ActionType;
    payload: number | Map<number, Node>;
}

然后你有功能:

export function productTreeReducer(state = initialState, action: productTreeOperations.Actions): State {...}

所以你的问题与类型不兼容有关。 State只能接受Map<>,但您实际返回Map<> OR number。在这种情况下,LoadProductTreeCompleteAction在构造函数中提供Map<>的事实并不重要,因为payload值可能会在运行时更改(外部由setter或内部更改通过状态变化/方法[即使它可能不存在])。

因此,您必须更改State的签名以接受这两种类型,如果您确定LOAD_PRODUCT_TREE_COMPLETE始终返回Map<>,则可以尝试

return { productTree: <Map<number, Node>>action.payload };