网站搜索

typescript - 类型 'AsyncThunkAction' 中缺少属性 'type',但在类型 'AnyAction' 中是必需的


代码:

import { configureStore, ConfigureStoreOptions, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import logger from 'redux-logger';

interface fetchUserResponse {
  name: string;
}

const fetchUser = createAsyncThunk<fetchUserResponse, void>('users/fetchUser', async () => {
  return { name: 'teresa teng' };
});

const usersSlice = createSlice({
  name: 'users',
  initialState: { name: '' },
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(fetchUser.fulfilled, (state, action) => {
      state.name = action.payload.name;
    });
  },
});

interface UserState {
  name: string;
}

interface AppState {
  user: UserState;
}

const storeConfig: ConfigureStoreOptions<AppState> = {
  reducer: {
    user: usersSlice.reducer,
  },
};

if (process.env.NODE_ENV !== 'production') {
  storeConfig.middleware = (getDefaultMiddlewares) => getDefaultMiddlewares().concat(logger);
}

const store = configureStore(storeConfig);

store.dispatch(fetchUser()); // TSC throws error

当我尝试分派 fetchUser() 动作时,TSC 会抛出以下错误。

类型为 'AsyncThunkAction' 的参数不能赋值给类型为 'AnyAction' 的参数。类型 'AsyncThunkAction' 中缺少属性 'type',而 'AnyAction' 类型中该属性是必需的。ts(2345)

需要传递哪些通用参数给通用类型 ConfigureStoreOptions 才能通过 TSC 类型检查。

软件包版本:

"@reduxjs/toolkit": "^1.5.0",
"typescript": "^4.1.2"

更新

如果我不使用ConfigureStoreOptions,当我尝试动态设置storeConfig的middleware属性时,我会得到以下错误。

属性 'middleware' 在类型 '{ reducer: { user: Reducer<{ name: string; }, AnyAction>; }; }' 上不存在。ts(2339)

答案#1

正如 @phry 所说,如果你直接调用 configureStore,可以完全跳过使用 ConfigureStoreOptions 类型:

const store = configureStore({
  reducer: {
    user: usersSlice.reducer
  }
});

在你的 storeConfig: ConfigureStoreOptions<AppState> 类型中缺少的部分是中间件类型的声明。当前类型不包括 thunk 或任何其他中间件,所以你无法分发 AsyncThunkAction。你需要调整你的 storeConfig 类型以支持 thunk。你可以通过设置第三个泛型类型参数 M 来实现这一点。

这是类型的定义方式:

ConfigureStoreOptions<S = any, A extends Action<any> = AnyAction, M extends Middlewares<S> = Middlewares<S>>

你需要直接从 "redux-thunk" 导入 ThunkMiddleware 类型,因为 "@reduxjs/toolkit" 并没有重新导出它。

import { configureStore, ConfigureStoreOptions } from "@reduxjs/toolkit";
import {ThunkMiddleware} from "redux-thunk";

const storeConfig: ConfigureStoreOptions<AppState, AnyAction, [ThunkMiddleware<AppState, AnyAction>]> = {
  reducer: {
    user: usersSlice.reducer
  }
};

const store = configureStore(storeConfig);

store.dispatch(fetchUser());

你可以这样做,并且它可以工作,但老实说,当你可以直接将选项传递给 configureStore 并获得所有类型推断时,这样做有点傻。

答案#2

redux-toolkit 维护者在此 👋

ConfigureStoreOptions 真的是一个你绝不应该手动使用的类型——它是通过实际调用 configureStore 来推断的。(我真的不知道如何手动为它设置类型,而我已经完成了当前 RTK 类型的大部分工作)

这实际上是我第一次见有人这样做。有什么特别迫切的原因让你一定要这样做吗?也许我可以提供一个替代方案。

看到你更新的代码后,我真的建议你做类似这样的事情

const store = configureStore({
  reducer: {
    user: usersSlice.reducer,
  },
  middleware(getDefaultMiddlewares) {
    if (process.env.NODE_ENV !== 'production') {
      return getDefaultMiddlewares().concat(logger);
    }
    else {
      return getDefaultMiddlewares()
    }
  }
});

你可以在这个游乐场看到它的运行情况