首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >还原机工厂打印问题中的Typescirpt映射

还原机工厂打印问题中的Typescirpt映射
EN

Stack Overflow用户
提问于 2019-01-11 22:25:16
回答 1查看 281关注 0票数 1

我正在尝试实现类型安全功能,以创建基于“动作处理程序”映射的还原器。这样做的目的是让API看起来像这样:

代码语言:javascript
复制
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函数(为了清晰起见没有类型记录)应该如下所示:

代码语言:javascript
复制
function createReducer(handlers, initialState) {
    return (state = initialState, action) => {
        if (action.type in handlers) {
            return handlers[action.type](state, action);
        }
        return state;
    };
}

我创建了这样的类型化函数以具有类型安全性:

代码语言:javascript
复制
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)

元素隐式具有“任意”类型,因为类型'ActionHandlers‘没有索引签名。

知道怎么在减速机内输入action.type吗?

您可以在要旨中找到整个示例

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-11 23:33:29

您得到错误的原因是action.type被隐式地键入为any,因为没有应用适用的类型。

在链的某一点上,您使用any作为需要根植于string的类型参数。

代码语言:javascript
复制
type ActionsCreators = {
    [creator: string]: ActionCreator<any>;
};

如果在这里添加一个类型参数,您可以替换any;但是,您需要一直传递它。

请参阅进行此更新的以下版本。我不得不将一些中间类型重命名为泛型名称(TP),因为我很难保持输入的正确性。

使用额外的类型参数<P>,我们现在有一个类型用于下面的内容,而不是隐式any

代码语言:javascript
复制
const f = handlers[action.type];

在这里,f变成了ActionHandlers<P, T, State>[P]

代码语言:javascript
复制
export interface Action<T extends string> {
    type: T;
}

export interface ActionWithPayload<T extends string, P> extends Action<T> {
    payload: P;
}

export type ActionCreator<T extends string> = (...args: any) => Action<T>;

export type ActionsCreators<T extends string> = {
    [creator: string]: ActionCreator<T>;
};

export type ActionsUnion<P extends string, T extends ActionsCreators<P>> = ReturnType<T[keyof T]>;

export type ActionHandlers<P extends string, T extends ActionsCreators<P>, State> = {
    [K in ReturnType<T[keyof T]>["type"]]: (
        state: State,
        action: ReturnType<T[K]>
    ) => State
};

export function createReducer<P extends string, State, T extends ActionsCreators<P>>(
    handlers: ActionHandlers<P, T, State>,
    initialState: State
) {
    return (state: State = initialState, action: ActionsUnion<P, T>): State => {

        if (action.type in handlers) {
            const f = handlers[action.type];
            return f(state, action);
        }

        return state;
    };
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54154856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档