带字符串插值的TypeScript推断

时间:2019-08-07 19:13:21

标签: typescript

我正在尝试重构一些通用的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还是有更好的处理方式?

0 个答案:

没有答案