【问题标题】:TypeScript: Removing index signature without getting implicitly has an 'any' type errorTypeScript:删除索引签名而不隐式出现“任何”类型错误
【发布时间】:2020-08-10 14:07:00
【问题描述】:

详情

我正在尝试创建一个辅助函数来将我的减速器组合成一个全局减速器,以便与 react 的 useReducer 钩子和上下文 API 一起使用。我有它的功能,但我目前对类型检查不满意。

问题

为了让它工作,我必须在 Reducers 类型中添加 [key: string]: Reducer<any>,在 GlobalState 类型中添加 [key: string]: any;。如果我删除它们,我会收到错误

元素隐含地具有“任何”类型,因为类型的表达式 'string' 不能用于索引类型 'GlobalState'。无索引 在类型上找到带有“字符串”类型参数的签名 '全球状态'。

元素隐含地具有“任何”类型,因为类型的表达式 'string' 不能用于索引类型'Reducers'。没有索引签名 在“Reducers”类型上找到了“字符串”类型的参数。

这给我留下了一个combineReducers 函数,我可以在其中将状态键命名为任何东西

一个例子

我的初始状态是这样的:{page: {some state}, state2: {some state}} 然后我像这样组合减速器:combineReducers({ pages: pageReducer, state3: reducer2 });

我现在的状态看起来像 {page: {some state}, state2: {some state}}, pages: {some state}, state3: {some state},因为“不小心”将状态键命名错误。

问题

在删除 Reducers 类型中的 [key: string]: Reducer<any> 和 GlobalState 类型中的 [key: string]: any; 时,有没有办法让它工作?

代码

types.ts

export type GlobalReducer = (state: GlobalState, action: Action) => GlobalState;
export type Reducer<State> = (state: State, action: Action) => State;

export type Reducers = {
    [key: string]: Reducer<any>;
    page: Reducer<PageState>;
    state2: Reducer<AnotherState>;
};

export type GlobalState = {
    [key: string]: any;
    page: PageState;
    state2: AnotherState;
};

export type PageState = {
    title: string;
    loading: true;
};

export type AnotherState = {
    hello: string;
};

combineReducers.ts

import _ from "lodash";

import { Action, Reducers, GlobalState, GlobalReducer } from "./types";

const combineReducers = (reducers: Reducers): GlobalReducer => {
    return (state: GlobalState, action: Action): GlobalState => {
        const reducerKeys = Object.keys(reducers);

        reducerKeys.forEach((key) => {
            const newState = reducers[key](state[key], action);
            state = _.isEqual(newState, state[key]) ? state : { ...state, [key]: newState };
        });

        return state;
    };
};

export { combineReducers };

index.ts

export const globalReducer = combineReducers({ page: pageReducer, state2: reducer2 });

initialState.ts

export const initialState: GlobalState = {
    page: {
        title: "Holidaze",
        loading: true
    },
    state2: {
        hello: ""
    }
};

【问题讨论】:

    标签: typescript


    【解决方案1】:

    Object.keys 返回一个字符串数组。你必须转换成keyof Reducers的数组。

    const reducerKeys = Object.keys(reducers) as (keyof Reducers)[];
    
    
    type GlobalState = {
        page: State1,
        anotherPage: AnotherState,
    }
    
    type GlobalReducer<State> = (state: State, action: Action) => State;
    type Reducer<State> = (state: State, action: Action) => State;
    
    type Reducers<State> = { [K in keyof State]: Reducer<State[K]> }
    
    const combineReducers = <State>(reducers: Reducers<State>): GlobalReducer<State> => {
        return (state: State, action: Action): State => {
            const reducerKeys = Object.keys(reducers) as (keyof State)[];
    
            reducerKeys.forEach((key) => {
                const newState = reducers[key](state[key], action);
                state = _.isEqual(newState, state[key]) ? state : { ...state, [key]: newState };
            });
    
            return state;
        };
    };
    
    

    【讨论】:

    • 这有帮助!但是我仍然收到 const newState = reducers[key](state[key], action); 行的错误。 'PageState | 类型的参数AnotherState' 不可分配给“PageState & AnotherState”类型的参数。是 state[key] 产生错误
    • 修复它!谢谢:)
    猜你喜欢
    • 2016-01-25
    • 1970-01-01
    • 2016-04-07
    • 2017-05-06
    • 2019-01-06
    • 1970-01-01
    • 2019-05-19
    • 2017-08-02
    • 2018-04-09
    相关资源
    最近更新 更多