【问题标题】:Typescript reducer打字稿减速器
【发布时间】:2021-03-20 15:00:11
【问题描述】:

当我试图通过 mapStateToProps 函数获取状态时,它给我的属性在类型 never 上不存在

这是reducer的sn-p设置代码,我这里也是用redux saga和redux persist

// combine all reducers
const rootReducer = combineReducers({
  dashboard: dashboardReducer,
  sales: salesReducer,
  auth: authReducer,
});

export type RootState = ReturnType<typeof rootReducer>;

// set config to our rootreducer
const pReducer = persistReducer(persistConfig, rootReducer); //ERROR ON rootReducer HERE

const sagaMiddleware = createSagaMiddleware();
// use the new persistreducer in creating store
const store = createStore(pReducer, composeEnhancers(applyMiddleware(sagaMiddleware)));

const persistor = persistStore(store);

注意:rootReducer 在我使用 persistReducer 设置持久配置时返回错误。

下面是我在persistReducer 函数中将鼠标悬停在rootReducer 上时出现的错误

const rootReducer: Reducer<CombinedState<{
    dashboard: never;
    sales: never;
    auth: never;
}>, AppActions>
Argument of type 'Reducer<CombinedState<{ dashboard: never; sales: never; auth: never; }>, AppActions>' is not assignable to parameter of type 'Reducer<unknown, AppActions>'.
  Types of parameters 'state' and 'state' are incompatible.
    Type 'unknown' is not assignable to type 'CombinedState<{ dashboard: never; sales: never; auth: never; }> | undefined'.
      Type 'unknown' is not assignable to type 'CombinedState<{ dashboard: never; sales: never; auth: never; }>'.
        Type 'unknown' is not assignable to type '{ readonly [$CombinedState]?: undefined; }'.ts(2345)

然后我尝试通过这样做来消除错误,这显然效果不佳,并导致之后出现type never 错误,但除了这样做之外,我不知道还有什么方法可以抑制错误。

const pReducer = persistReducerRootState>(persistConfig, rootReducer);

然后在我尝试获取状态时在我的一个 TSX 文件中

interface StateProps {
  loading: boolean;
  authenticated: boolean;
  errorMessage: string | null;
  userInfoObj: TReceivedUserInfoObj | null;
}
const mapStateToProps = (state: RootState): StateProps | void => {
  return {
    loading: state.auth.loading,
    errorMessage: state.auth.errorMessage,
    userInfoObj: state.auth.userInfoObj,
    authenticated: state.auth.auth_token !== null,
  };
};

而且它让我输入永远不会出错

Property 'loading' does not exist on type 'never'.  TS2339

    108 | const mapStateToProps = (state: RootState): StateProps | void => {
    109 |   return {
  > 110 |     loading: state.auth.loading,
        |                         ^
    111 |     errorMessage: state.auth.errorMessage,
    112 |     userInfoObj: state.auth.userInfoObj,
    113 |     authenticated: state.auth.auth_token !== null,

此外,当我将鼠标悬停在 &lt;typeof rootReducer&gt; 上时,这就是我所看到的

const rootReducer: Reducer<CombinedState<{
    dashboard: never;
    sales: never;
    auth: never;
}>, AppActions>

authReducer 当我将鼠标悬停在它上面时

(alias) const authReducer: (state: AuthInitialState | undefined, action: AuthActionTypes) => {} | undefined
import authReducer

AuthInitialState auth reducer 中初始状态的类型

// initialState for reducers
export interface AuthInitialState {
  readonly loading: boolean;
  readonly errorMessage: string | null;
  readonly successMessage: string | null;
  // user info
  readonly userInfoObj: TReceivedUserInfoObj | null;
  // auth token
  readonly auth_token: string | null;
}

AuthActionTypes 一堆动作接口合并为一个类型

export type AuthActionTypes = 
  | SignInAction
  | SignInStartAction
  | SignInSucceedAction
  | SignInFailedAction
 
  | SignOutAction
 
  | GetUserInfoAction
  | GetUserInfoStartAction
  | GetUserInfoSucceedAction
  | GetUserInfoFailedAction;

登录操作示例

export interface SignInAction {
  type: typeof actionTypes.SIGN_IN;
  email: string;
  password: string;
}

export interface SignInStartAction {
  type: typeof actionTypes.SIGN_IN_START;
}

export interface SignInSucceedAction {
  type: typeof actionTypes.SIGN_IN_SUCCEED;
  auth_token: string;
}

export interface SignInFailedAction {
  type: typeof actionTypes.SIGN_IN_FAILED;
  errorMessage: string;
}

简而言之,我的问题是无法顺利设置rootReducer,redux persist 并在通过 mapStateToProps 提取状态时导致状态类型为 never

如果帖子有点太长且难以阅读,我深表歉意,感谢您的耐心和提前帮助。


更新 我看到了这个 post 并实现了 Reducer 的东西。现在never 类型的错误消失了,但是出现了新的问题。

在我的 auth.ts reducer 文件中,

const reducer: Reducer<AuthInitialState, AuthActionTypes> = (state = initialState, action) => {

现在给我这个错误

const reducer: Reducer<AuthInitialState, AuthActionTypes>
Type '(state: AuthInitialState | undefined, action: AuthActionTypes) => {} | undefined' is not assignable to type 'Reducer<AuthInitialState, AuthActionTypes>'.
  Type '{} | undefined' is not assignable to type 'AuthInitialState'.
    Type 'undefined' is not assignable to type 'AuthInitialState'.ts(2322)

【问题讨论】:

  • Typescript 应该足够聪明,可以推断出正确的错字。您可以简单地删除 : any 并让 typescript 自动分配/推断正确的类型,
  • 能否请您向我们展示您做了什么以及您遇到了什么错误?正如@Rumpelstinsk 正确指出的那样,让打字稿来推断正确的类型。
  • 添加了更多关于我做了什么的细节,我真的不知道我在这里用 redux 类型做什么,我只是按照 youtube 上的一些教程并模仿他们为他们的 mapStateToProps 声明类型的方式和mapDispatchToProps

标签: reactjs typescript redux


【解决方案1】:

请注意,我们不必为 RootState 显式声明新接口。我们可以使用ReturnTyperootReducer 推断状态形状。

const rootReducer = combineReducers({
  dashboard: dashboardReducer,
  sales: salesReducer,
  auth: authReducer,
});

export type RootState = ReturnType<typeof rootReducer>

checkout this official redux docs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2021-12-21
    • 2020-04-20
    • 2019-01-13
    • 2017-09-22
    相关资源
    最近更新 更多