打字稿显然为派遣的 Thunk 推断出错误的类型 [英] Typescript apparently deduces the wrong type for a dispatched Thunk

查看:40
本文介绍了打字稿显然为派遣的 Thunk 推断出错误的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

完整的代码和盒子示例 这里

我声明了一个简单的动作类型和一个调度它的异步 thunk:

I declare a simple action type and an asynchronous thunk that dispatches it:

type ActionType = { type: "foo"; v: number };

const FooThunk: ThunkAction<Promise<ActionType>, any, any, ActionType> = (dispatch): Promise<ActionType>
=> {
  return new Promise<number>((resolve) => {
    setTimeout(() => {
      resolve(42);
    }, 100);
  }).then((v: number) => {
    return dispatch({ type: "foo", v });
  });
};

现在的问题是当我调用 dispatch(FooThunk) 时我得到的值的类型是什么.Typescript 认为类型是 ThunkAction, any, any, ActionType> 并用以下消息抱怨(在沙箱的第 38 行):

The question is now what is the type of the value I get when I call dispatch(FooThunk). Typescript thinks the type is ThunkAction<Promise<ActionType>, any, any, ActionType> and complains (on line 38 of the sandbox) with the following message:

'ThunkAction<Promise<ActionType>, any, any, ActionType>' is missing the following properties from type 'Promise<ActionType>': then, catch, [Symbol.toStringTag]ts(2739)

但是,当我记录在运行时获得的值(代码和框的第 48 行)时,我清楚地看到它是一个 Promise.在 StackOverflow 上搜索我发现了矛盾的答案.这个答案 说调度 thunk 会返回 thunk 本身.而 这个答案 表明分派 thunk 会返回一个 Promise.

However, when I log the value I get at runtime (line 48 of the codesandbox) I see clearly that it is a Promise. Searching on StackOverflow I have found contradictory answers. This answer says that dispatching a thunk returns the thunk itself. Whereas this answer suggests that dispatching a thunk returns a Promise.

Typescript 的类型系统似乎说调度 thunk 的类型与 thunk 本身是一样的.但是在运行时我得到一个 Promise 对象.我错过了什么?

Typescript's type system seems to say that the type of dispatching a thunk is the same as the thunk itself. However at runtime I get a Promise object. What am I missing?

仅出于完整性目的,我附加了您将找到沙箱的代码(上面提供了链接):

For completeness purposes only, I append the code that you will find the the sandbox (link provided above):

import * as React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import { initialState, rootReducer } from "./rootReducer";
import "./styles.css";

import { ThunkDispatch as Dispatch, ThunkAction } from "redux-thunk";
import { connect, ConnectedProps } from "react-redux";

import { applyMiddleware } from "redux";

import thunk from "redux-thunk";

const store = createStore(
  rootReducer /* preloadedState, */,
  applyMiddleware(thunk)
);

//const store = createStore(rootReducer, initialState);

type ActionType = { type: "foo"; v: number };

const FooThunk: ThunkAction<Promise<ActionType>, any, any, ActionType> = (
  dispatch
): Promise<ActionType> => {
  return new Promise<number>((resolve) => {
    setTimeout(() => {
      resolve(42);
    }, 100);
  }).then((v: number) => {
    return dispatch({ type: "foo", v });
  });
};

const mapDispatchToProps = (dispatch: Dispatch<any, any, any>) => {
  return {
    dispatchFooThunk: (): Promise<ActionType> => dispatch(FooThunk)
  };
};
const connector = connect(null, mapDispatchToProps);

type PropsFromRedux = ConnectedProps<typeof connector>;

class FooComponent_ extends React.Component<PropsFromRedux> {
  componentDidMount() {
    const p = this.props.dispatchFooThunk();
    console.log(p); // if you examine log output you see clearly that this is a PROMISE !
  }
  render() {
    return <div>foo</div>;
  }
}

const FooComponent = connector(FooComponent_);

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <FooComponent />
      </Provider>
    );
  }
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);

推荐答案

thunk 的返回值是 thunk 操作本身的返回值.结果是:如果它是一个异步函数,它会返回一个 Promise.

The return value of a thunk is the return value of the thunk action itself. As a consequence: If it's an async function, it returns a Promise.

虽然普通的 Dispatch 类型不知道如何处理 thunk.如果您使用的是 redux 工具包 本文档部分 描述了如何使用从商店配置推断出的 Dispatch 类型正确键入 useDispatch 钩子.如果你使用普通的 redux,你可以使用 ThunkDispatch 类型.react-redux 文档的这一部分 描述了在这种情况下如何输入 useDispatch 钩子.

The normal Dispatch type does not know how to handle thunks though. If you are using redux toolkit this documentation part describes how to properly type your useDispatch hook with a Dispatch type inferred from the store configuration. If you are using plain redux, you just can use the ThunkDispatch type. This part of the react-redux documentation describes how to type your useDispatch hook in that case.

PS:在您的特定情况下,您的 ThunkDispatch 太通用了.最后一个 any 会太急切地匹配.尝试使用 ThunkDispatch 代替,它会起作用.

PS: in your specific case, your ThunkDispatch<any, any, any> is too generic. That last any will match too eagerly. Try a ThunkDispatch<any, any, AnyAction> instead, that will work.

这篇关于打字稿显然为派遣的 Thunk 推断出错误的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆