异步调度值的 TypeScript 类型



我有以下异步操作定义:

import {Dispatch} from 'react';
import axios, {AxiosResponse, AxiosError} from 'axios';
function asyncAction() {
return (dispatch: Dispatch<any>): Promise<number> => {
return axios.get('http://www.example.com')
.then( (res: AxiosResponse<any>) => {
return 1;
})
.catch( (err: AxiosError<any>) => {
return 2;
});
}
}

上面的类型检查很好。

我也明白,当您调用dispatch并向其传递异步操作时,如下所示:

dispatch(asynAction())

。然后返回类型,如果是内部函数的类型,所以我希望上述值的类型是Promise<number>的。然而,以下内容没有进行类型检查:

function foo (dispatch: Dispatch<any>) {
const n: Promise<number> = dispatch(asyncAction()); // line A
}

具体来说,我在line A上收到以下错误:

TS2322: Type 'void' is not assignable to type 'Promise<number>'

所以,为了满足TS,我必须做一些感觉不对的事情:

const n: Promise<number> = dispatch(asyncAction()) as unknown as Promise<number>;

我错过了什么?

更新

我的"包.json"有:
"@types/react-redux": "^7.1.9",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.8",
"redux-thunk": "^2.3.0"

当我执行以下操作时:

import {ThunkDispatch as Dispatch} from 'redux-thunk';

。并使用导入的ThunkDispatch类型作为ThunkDispatch<any, any, any>(我在上面的代码中Dispatch<any>的任何位置),如下所示:

import axios, {AxiosResponse
, AxiosError} from 'axios';
import {ThunkDispatch as Dispatch} from 'redux-thunk';
export function asyncAction() {
return (dispatch: Dispatch<any, any, any>): Promise<number> => {
return axios.get('http://www.example.com')
.then( (res: AxiosResponse<any>) => {
return 1;
})
.catch( (err: AxiosError<any>) => {
return 2;
});
}
}
export function foo (dispatch: Dispatch<any, any, any>) {
const n: Promise<number> = dispatch(asyncAction());
console.log(n);
}

。我收到不同的错误:

TS2739: Type '(dispatch: ThunkDispatch<any, any, any>) => Promise<number>' is missing the following properties from type 'Promise<number>': then, catch, [Symbol.toStringTag]

不同的包对Dispatch类型有不同的定义。 您正在从"反应"导入一个,这不符合您的需求。

Redux 声明调度返回操作:

export interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T
}

React,它定义了Dispatch,以达到它自己的useReducer钩子(redux-lite)的目的,说它不返回任何内容:

type Dispatch<A> = (value: A) => void;

Thunk 有一个更复杂的定义,它允许它基于泛型返回任何任意返回类型:

export interface Dispatch<A extends Action = AnyAction> {
<TReturnType = any, TState = any, TExtraThunkArg = any>(
thunkAction: ThunkAction<TReturnType, TState, TExtraThunkArg, A>,
): TReturnType;
}

您的第一个示例有效,因为您从未实际调用过dispatch函数,并且返回类型与axios调用的返回类型匹配。 您在第二个示例中遇到了相同的问题。

asyncAction()不会调度操作。Promise<number>操作创建者的返回类型,而不是调度的返回类型。 有关缺少属性的错误基本上告诉您调度不会返回Promise

您以非常混乱和混乱的方式编写了asyncAction,但基本上它是一个返回一个函数的函数,该函数接受dispatch并返回Promise<number>。 因此,基于此,您获得Promise<number>foo的方式不是使用函数调用dispatch,而是将dispatch作为参数传递给通过调用ayncAction()创建的函数。

export function foo (dispatch: Dispatch<any, any, any>) {
const n: Promise<number> = asyncAction()(dispatch);
console.log(n);
}

这当然没有意义,因为您仍然从未在任何地方发送任何东西。

打字稿游乐场链接

编辑:

希望这对您要做的事情有所帮助。 希望从dispatch的返回值中获取n只是为了测试,因为你不能也不应该这样做。

让我们定义最终将调度的操作,以及它的创建者。

import { Action } from "redux";
// normal action type
interface NumberAction extends Action {
payload: number;
}
// normal action creator
function sendNumber(number: number): NumberAction {
return { type: 'SEND_NUMBER', payload: number };
}

我们制作了一个ThunkAction来发送此NumberAction。 它是一个函数,它将dispatch作为参数,并为它最终调度的操作返回Promise

const myThunkAction1: ThunkAction<Promise<NumberAction>, any, any, NumberAction> = (dispatch): Promise<NumberAction> => {
return axios.get('http://www.example.com')
.then((res: AxiosResponse<any>) => {
return 1;
})
.catch((err: AxiosError<any>) => {
return 2;
})
.then(number => dispatch(sendNumber(number)));
}

我们可以dispatch这一点,但它返回ThunkAction本身。 换句话说,调用dispatch返回一个需要dispatch的函数。 因此,您无法从调度 thunk 的返回值中获得任何有意义的东西。

export function foo(dispatch: Dispatch<any, any, any>) {
// still doesn't return Promise<number>, returns the ThunkAction
const returned = dispatch(myThunkAction2);
// can only get to Promise<number> by calling the returned thunk, which would re-dispatch the action
const n: Promise<number> = returned(dispatch, () => {}, {});
console.log(n);
}

第二个游乐场链接

相关内容

  • 没有找到相关文章

最新更新