我想让react reducer函数更加通用,并将动作处理程序分离成函数。
export type Actions =
| {
type: "ADD_COLUMN";
newColumnIndex: number;
column: SelectorColumnData;
}
| {
type: "ITEM_CHECKED";
columnIndex: number;
item: SelectorItem;
};
export type ActionTypes = Actions["type"];
// type ActionTypes = "ADD_COLUMN" | "ITEM_CHECKED";
这对我来说很有意义:
const reducerRecord: Record<ActionTypes, (draft: Draft<SelectorState>, action: Actions) => void> = {
"ITEM_CHECKED": itemCheckedAction,
"ADD_COLUMN": addColumnAction,
};
export const selectorReducer: ImmerReducer<SelectorState, Actions> = (
draft: Draft<SelectorState>,
action: Actions,
): void => {
reducerRecord[action.type](draft, action);
};
我的动作处理程序:
export const itemCheckedAction = (draft: Draft<SelectorState>, action: Actions) => {
const { columnIndex, item } = action;
// ...
}
TypeScript不喜欢这个(TS2339: property 'columnIndex' does not exist on type 'Actions'
),所以我尝试了这个:
export const itemCheckedAction = (draft: Draft<SelectorState>, action: Actions) => {
const { columnIndex, item }: Extract<Actions, { type: "ITEM_CHECKED" }> = action;
// ...
}
也不喜欢这个!它说“ADD_COLUMN”类型丢失了。
奇怪的是,如果我写:
export const itemCheckedAction = (draft: Draft<SelectorState>, action: Actions) => {
if(action.type === "ITEM_CHECKED") {
const { columnIndex, item }: Actions = action;
}
// ...
}
...将鼠标悬停在= action
上会显示所需的联合子类型,但IDE仍然抱怨columnIndex
和item
不是Actions
的属性。
有什么想法吗?
1条答案
按热度按时间pes8fvy91#
您需要强制参数进行区分。最简单的方法是将其与目标
type
变量相交:TypeScriptPlayground链接