如何将 Redux 4.0 TypeScript 绑定与 redux-thunk 结合使用
How to use Redux 4.0 TypeScript bindings with redux-thunk
我在使用 Redux 4.0 的新 TS 绑定和 redux-thunk 时遇到问题。我通过转换基本的 Redux "Todo List" example to TypeScript (repo here), and making the Add Todo action a thunk. The problem is the same as reported here 重现了这个问题:Argument of type 'ThunkAction' is not assignable to parameter of type 'AnyAction'。
属性 'type' 在类型 'ThunkAction' 中缺失。
基本上,我可以让它工作,但我在一些我认为不应该使用的地方使用 any
。一个地方是 index.tsx#L14,我在其中将 thunk 中间件添加到商店:
const store = createStore(
rootReducer,
applyMiddleware(thunk as ThunkMiddleware<IRootState, any>)
);
如果我在那里使用 any
以外的任何东西,那么下一行会抛出错误:
store.dispatch(addTodo('Use redux-thunk'));
另一个地方是AddTodo.tsx#L7,我在这里声明了由connect
函数注入的dispatch prop:
interface IAddTodoProps {
dispatch: Dispatch<any>;
}
const AddTodo = ({ dispatch }: IAddTodoProps) => {
...
}
export default connect()(AddTodo);
在这两个地方,any
覆盖了必须扩展 Action<any>
的类型。 Action
需要一个 type
属性,这当然是 thunk 所没有的。我如何声明这些类型以便 dispatch
函数接受一个 thunk?
Related question
Relevant PR
diff --git a/src/containers/AddTodo.tsx b/src/containers/AddTodo.tsx
index e49ac4a..20a93d6 100644
--- a/src/containers/AddTodo.tsx
+++ b/src/containers/AddTodo.tsx
@@ -1,10 +1,12 @@
import * as React from 'react';
import { connect } from 'react-redux';
-import { Dispatch } from 'redux';
+import { ThunkDispatch } from 'redux-thunk';
+import { AnyAction } from 'redux';
import { addTodo } from '../actions';
+import { IRootState } from '../reducers/index';
interface IAddTodoProps {
- dispatch: Dispatch<any>;
+ dispatch: ThunkDispatch<IRootState,any,AnyAction>;
}
const AddTodo = ({ dispatch }: IAddTodoProps) => {
这个问题(以及许多其他问题)的答案原来是:使用 Redux Toolkit。
商店设置非常简单:
// src/redux/store.ts
import { configureStore } from '@reduxjs/toolkit';
import reducer from './reducers';
const store = configureStore({ reducer });
export type AppDispatch = typeof store.dispatch;
export default store;
然后在使用 react-redux
中的 useDispatch
挂钩时,只需将其键入 AppDispatch
:
// src/components/App.tsx
import { useDispatch } from 'react-redux';
import { AppDispatch } from '../redux/store';
const App = () => {
const dispatch: AppDispatch = useDispatch();
// ...
}
我在使用 Redux 4.0 的新 TS 绑定和 redux-thunk 时遇到问题。我通过转换基本的 Redux "Todo List" example to TypeScript (repo here), and making the Add Todo action a thunk. The problem is the same as reported here 重现了这个问题:Argument of type 'ThunkAction' is not assignable to parameter of type 'AnyAction'。 属性 'type' 在类型 'ThunkAction' 中缺失。
基本上,我可以让它工作,但我在一些我认为不应该使用的地方使用 any
。一个地方是 index.tsx#L14,我在其中将 thunk 中间件添加到商店:
const store = createStore(
rootReducer,
applyMiddleware(thunk as ThunkMiddleware<IRootState, any>)
);
如果我在那里使用 any
以外的任何东西,那么下一行会抛出错误:
store.dispatch(addTodo('Use redux-thunk'));
另一个地方是AddTodo.tsx#L7,我在这里声明了由connect
函数注入的dispatch prop:
interface IAddTodoProps {
dispatch: Dispatch<any>;
}
const AddTodo = ({ dispatch }: IAddTodoProps) => {
...
}
export default connect()(AddTodo);
在这两个地方,any
覆盖了必须扩展 Action<any>
的类型。 Action
需要一个 type
属性,这当然是 thunk 所没有的。我如何声明这些类型以便 dispatch
函数接受一个 thunk?
Related question
Relevant PR
diff --git a/src/containers/AddTodo.tsx b/src/containers/AddTodo.tsx
index e49ac4a..20a93d6 100644
--- a/src/containers/AddTodo.tsx
+++ b/src/containers/AddTodo.tsx
@@ -1,10 +1,12 @@
import * as React from 'react';
import { connect } from 'react-redux';
-import { Dispatch } from 'redux';
+import { ThunkDispatch } from 'redux-thunk';
+import { AnyAction } from 'redux';
import { addTodo } from '../actions';
+import { IRootState } from '../reducers/index';
interface IAddTodoProps {
- dispatch: Dispatch<any>;
+ dispatch: ThunkDispatch<IRootState,any,AnyAction>;
}
const AddTodo = ({ dispatch }: IAddTodoProps) => {
这个问题(以及许多其他问题)的答案原来是:使用 Redux Toolkit。
商店设置非常简单:
// src/redux/store.ts
import { configureStore } from '@reduxjs/toolkit';
import reducer from './reducers';
const store = configureStore({ reducer });
export type AppDispatch = typeof store.dispatch;
export default store;
然后在使用 react-redux
中的 useDispatch
挂钩时,只需将其键入 AppDispatch
:
// src/components/App.tsx
import { useDispatch } from 'react-redux';
import { AppDispatch } from '../redux/store';
const App = () => {
const dispatch: AppDispatch = useDispatch();
// ...
}