我正在尝试编写一个帮助程序,让我订阅 React 应用程序中特定类型的调度操作。这些是我正在使用的操作界面:
enum ActionTypes {
MoveToLine = 'MOVE_TO_LINE',
MoveToColumn = 'MOVE_TO_COLUMN',
}
interface MoveToLineAction {
type: ActionTypes.MoveToLine;
payload: { line: number };
}
interface MoveToColumnAction {
type: ActionTypes.MoveToColumn;
payload: { column: number };
}
type Actions = MoveToLineAction | MoveToColumnAction;
这是subscribeToAction
的实现:
const subscribeToAction = <A extends { type: string }, T extends ActionTypes>(
type: T,
onAction: (a: A) => void,
) => (action: A) => {
if (action.type === type) {
onAction(action);
}
};
我希望能够像这样使用它:
// Subscribe to a specific type of action
subscribeToAction(ActionTypes.MoveToLine, action => {
action.payload.line;
});
我遇到的问题是我希望自动推断onAction
侦听器中的action
类型。在上面的代码中,我收到一个Property 'payload' does not exist on type '{ type: string; }'
错误。我可以手动键入侦听器来解决此问题,如下所示:
subscribeToAction(ActionTypes.MoveToLine, (action: MoveToLineAction) => {
action.payload.line;
});
但是,传入ActionType
然后还必须在侦听器中指定操作类型似乎是多余的。你们对如何避免这样做有什么建议吗?
以下是我的做法:
type ActionOfType<T extends ActionTypes> = Extract<Actions, { type: T }>;
const subscribeToAction = <T extends ActionTypes>(
type: T,
onAction: (a: ActionOfType<T>) => void,
) => (action: Actions) => {
if (action.type === type) {
// assertion necessary or explicit type guard:
onAction(action as ActionOfType<T>);
}
};
subscribeToAction(ActionTypes.MoveToLine,
action => { // action inferred as MoveToLineAction
action.payload.line;
}
);
您实际上不希望subscribeToAction()
中使用两个通用参数。 您希望T
对应于作为type
传入的ActionTypes
成分,并且您希望onAction
回调的参数自动约束为Actions
的相应成分。 ActionOfType<T>
类型函数显示如何执行此操作。 哦,subscribeToAction
的返回值应该是一个接受任何Actions
的函数,对吧? 这就是您进行if (action.type === type)
检查的原因。
另请注意,由于action
属于 Actions
类型,因此您需要告诉编译器,测试if (action.type === type)
实际上将action
缩小到ActionOfType<T>
。 我只是使用类型断言。
好的,希望对您有所帮助。 祝你好运!