在 React/Redux initialState 上,类型“字符串”不可分配给类型“未定义”错误

时间:2021-04-28 08:30:30

标签: typescript redux react-redux react-typescript

我在创建商店时在我的 initialState 上收到一个 lint 错误 Type 'string' is not assignable to type 'undefined'

以下是相关部分的简化表示:

export interface IGeneric {
  aString: string;
  aNumber: number;
}

interface IAppState {
  currentSection: string;
  experiences: IGeneric[] | [];
  finishedScenario: boolean;
  formation: IGeneric[] | [];
  language: LanguageCode;
  languages: IGeneric[] | [];
  projects: IGeneric[] | [];
  skills: IGeneric[] | [];
  texts: IGeneric | Record<string, never>;
  textsDatabase: IGeneric | Record<string, never>;
}

const INITIAL_STATE: IAppState = {
  currentSection: 'main',
  experiences: [],
  finishedScenario: false,
  formation: [],
  language: 'en',
  languages: [],
  projects: [],
  skills: [],
  texts: {},
  textsDatabase: {}
};


let store: Store;

export const getStore = (): Store<IAppState> => {
  if (!store) {
    store = createStore(
      rootReducer,
      INITIAL_STATE, // error here
      compose(applyMiddleware(thunk, updateTexts), devToolsEnhancer())
    );
  }
  return store;
};

initial state error image

关于如何解决它的任何想法? 谢谢!

更新:

似乎在我的 combineReducers 中,我的所有状态值都默认初始化 undefined,根据 Redux 定义,all reducers are passed undefined on initialization 那么好吧。我得到了那部分......但问题仍然存在......如何应对它并使我的 createStore 接受未定义和其初始状态的真实接口? ?

2 个答案:

答案 0 :(得分:0)

好的...在我非常努力地挣扎并阅读了数以千计的文档之后,我找到了解决方案。我把它贴在这里,以防将来对其他人有帮助。

真正让我大开眼界的是this Github issuethis discussion on SO。 我缺少的是:

"With combineReducers, each slice reducer is expected to "own" its slice of state. That means providing an initial value in case the current slice is undefined, and combineReducers will point out if you're not doing that."

"Your reducers currently do nothing except return whatever's passed in. That means that if state is undefined, they will return undefined. So, combineReducers() is telling you you're breaking the result that it expects."

因此,很明显我的问题发生在我的 conbineReducers 上,我重写了它的类型定义以允许未定义的值。

这是它的最终实现(为了简化,为 IGeneric 更改了实际接口):

type IActionReducer<T> = (state: T, action: IAction<T>) => T;

interface RootReducer {
  currentSection: IActionReducer<IGeneric| undefined>;
  experiences: IActionReducer<IGeneric[] | [] | undefined>;
  finishedScenario: IActionReducer<boolean | undefined>;
  formation: IActionReducer<IGeneric[] | [] | undefined>;
  language: IActionReducer<IGeneric| undefined>;
  languages: IActionReducer<IGeneric[] | [] | undefined>;
  projects: IActionReducer<IGeneric[] | [] | undefined>;
  skills: IActionReducer<IGeneric[] | [] | undefined>;
  texts: IActionReducer<IGeneric| Record<string, never> | undefined>;
  textsDatabase: IActionReducer<IGeneric| Record<string, never> | undefined>;
}

const rootReducer = combineReducers({
  currentSection,
  experiences,
  finishedScenario,
  formation,
  language,
  languages,
  projects,
  skills,
  texts,
  textsDatabase
} as RootReducer);

export default rootReducer;

我真的希望这能帮助有类似问题的人。 :)

答案 1 :(得分:-1)

您没有在初始状态中放置第一个道具的结束语。您的初始状态应该:

const INITIAL_STATE: IAppState = {
  currentSection: 'main',
  ....
};