问题描述
我正在使用redux-thunk
来使用异步操作创建器。结果也会返回给各自的调用方。
function fetchUserName(userId: number): Promise<string> {
return Promise.resolve(`User ${userId}`)
}
function requestUserName(userId: number) {
return (dispatch: Dispatch) => {
return fetchUserName(userId).then(name => {
dispatch({
type: 'SET_USERNAME',
payload: name,
})
})
}
}
这样可以更新存储区,同时允许组件直接处理响应。
function User() {
const dispatch = useDispatch()
useEffect(() => {
dispatch(requestUserName(1))
.then(name => {
console.log(`user name is ${name}`)
})
.catch(reason => {
alert('failed fetching user name')
})
}, [])
}
这按预期工作,但由于类型无效,它将不会由TypeScript编译。
useDispatch
返回的dispatch
未被识别为返回承诺的函数,因此TypeScript认为Property 'then' does not exist on type '(dispatch: Dispatch<AnyAction>) => Promise<void>'.
。
即使它会被识别,也应该正确键入承诺
如何解决此情况?
我可以围绕useDispatch
创建包装器,或者重新定义dispatch
的类型,但我不知道该类型在这种特定情况下应该是什么样子。
非常感谢您的建议。
推荐答案
useDispatch
返回Dispatch
类型used by Redux,因此只能随其一起调度标准动作。若要也分派thunk操作,请将其类型声明为ThunkDispatch
(来自redux-thunk
)。
ThunkDispatch
接收存储状态的类型参数extra thunk args和您的操作类型。可以派发一个ThunkAction
,这基本上是requestUserName
的内部函数。
例如,您可以这样键入:
import { ThunkDispatch } from "redux-thunk";
import { AnyAction } from "redux";
type State = { a: string }; // your state type
type AppDispatch = ThunkDispatch<State, any, AnyAction>;
// or restrict to specific actions instead of AnyAction
function User() {
const dispatch: AppDispatch = useDispatch();
useEffect(() => {
dispatch(requestUserName(1))
.then(...) // works now
}, []);
...
}
AppDispatch
也可以inferred从商店购买typeof store.dispatch
:
import thunk, { ThunkDispatch, ThunkMiddleware } from "redux-thunk";
const mw: ThunkMiddleware<State, AnyAction> = thunk;
const dummyReducer = (s: State | undefined, a: AnyAction) => ({} as State);
const store = createStore(dummyReducer, applyMiddleware(mw));
type AppDispatch = typeof store.dispatch // <-- get the type from store
TS Playground sample
另请参阅Redux有关将TypeScript与挂钩一起使用的文档:https://redux.js.org/usage/usage-with-typescript#define-typed-hooks