我正在尝试重构一些通用的reducer逻辑,并遇到了使用模板字符串推断类型的问题。
例如,假设我有一个减速器:
const LIST_PAGE = 'LIST_PAGE'
const LIST_SEARCH = 'LIST_SEARCH'
export interface ListState {
pager: {
currentPage: number
}
search: {
query: string
}
}
export interface PageListAction {
type: typeof LIST_PAGE
payload: {
currentPage: number
}
}
export interface SearchListAction {
type: typeof LIST_SEARCH
payload: {
query: string
}
}
type ListActions = PageListAction | SearchListAction
const listReducer = (state: ListState, action: ListActions): ListState => {
switch (action.type) {
case LIST_PAGE:
return {
...state,
pager: {
currentPage: action.payload.currentPage
}
};
case LIST_SEARCH:
return {
...state,
search: {
query: action.payload.query
}
};
default:
return state
}}
TypeScript能够根据其type
属性来推断操作的类型。
现在,我尝试将某些通用逻辑重构为“集合缩减器”,如下所示:
export interface CollectionState {
pager: {
currentPage: number
},
search: {
query: string
}
}
export interface PageCollectionAction {
type: string
payload: {
currentPage: number
}
}
export interface SearchCollectionAction {
type: string
payload: {
query: string
}
}
type CollectionActions = PageCollectionAction | SearchCollectionAction
const LIST: string = 'LIST'
const LIST_PAGE: string = 'LIST_PAGE'
const LIST_SEARCH: string = 'LIST_SEARCH'
export interface ListState extends CollectionState {}
export interface PageListAction extends PageCollectionAction {
type: typeof LIST_PAGE
}
export interface SearchListAction extends SearchCollectionAction {
type: typeof LIST_SEARCH
}
type ListActions = PageListAction | SearchListAction
function createCollectionReducer<S extends CollectionState, T extends CollectionActions>(collectionType:string) {
const collectionReducer = (state: S, action: T): S => {
switch (action.type) {
case `${collectionType}_PAGE`:
return {
...state,
pager: {
currentPage: action.payload.currentPage
}
};
case `${collectionType}_SEARCH`:
return {
...state,
search: {
query: action.payload.query
}
};
default:
return state
}}
return collectionReducer
}
const listReducer = createCollectionReducer<ListState, ListActions>(LIST)
这有效,但是由于字符串插值,TypeScript不再能够推断操作类型。我知道为什么它不起作用,但是我在这里找不到合适的方法。我应该使用包含所有动作类型的enum
还是有更好的处理方式?