【发布时间】:2019-06-06 20:49:33
【问题描述】:
我正在尝试实现类型安全的功能,以创建基于“动作处理程序”映射的减速器。我们的想法是让 API 看起来像这样:
export const Actions = {
setToken: (token: string) => createAction(SET_TOKEN_TYPE, token),
invalidateToken: () => createAction(INVALIDATE_TOKEN_TYPE),
startLogin: () => createAction(START_LOGIN_TYPE)
};
export const reducer = createReducer<State, typeof Actions>(
{
[SET_TOKEN_TYPE]: ({ loginError, ...state }, action) => ({
...state,
token: action.payload,
loading: false
}),
[INVALIDATE_TOKEN_TYPE]: ({ token, ...state }) => state,
[START_LOGIN_TYPE]: ({ loginError, ...state }) => ({
...state,
loading: true
})
},
{
loading: false
}
);
createReducer 函数应该(为了清楚起见没有 Typescript)看起来像这样:
function createReducer(handlers, initialState) {
return (state = initialState, action) => {
if (action.type in handlers) {
return handlers[action.type](state, action);
}
return state;
};
}
我创建了这样的类型化函数来保证类型安全:
interface Action<T extends string> {
type: T;
}
type ActionCreator<T extends string> = (...args: any) => Action<T>;
type ActionsCreators = {
[creator: string]: ActionCreator<any>;
};
type ActionsUnion<Actions extends ActionsCreators> = ReturnType<
Actions[keyof Actions]
>;
type ActionHandlers<ActionCreators extends ActionsCreators, State> = {
[K in ReturnType<ActionCreators[keyof ActionCreators]>["type"]]: (
state: State,
action: ReturnType<ActionCreators[K]>
) => State
};
function createReducer<State, Actions extends ActionsCreators>(
handlers: ActionHandlers<Actions, State>,
initialState: State
) {
return (
state: State = initialState,
action: ActionsUnion<Actions>
): State => {
if (action.type in handlers) {
// unfortunately action.type is here any :(
return handlers[action.type](state, action); // here I have the error
}
return state;
};
}
在handlers[action.type] 我有错误(noImplicitAny: true)
元素隐含地具有“any”类型,因为类型“ActionHandlers”没有索引签名。
知道如何在 reducer 中输入 action.type 吗?
你可以在the gist找到整个例子
【问题讨论】:
标签: typescript redux typescript-typings mapped-types