Typescript 财产';然后';通过bindActionCreators绑定的函数上不存在

Typescript 财产';然后';通过bindActionCreators绑定的函数上不存在,typescript,redux,react-redux,Typescript,Redux,React Redux,我已经按照官方的Redux指南创建了thunk动作创建者,这样我就可以在react组件中使用绑定动作。但是,我的组件无法识别函数返回的承诺,因此我不能使用then,这也意味着我无权访问函数的返回值 以下是我的action creator代码示例: // Temp State for now, not important type IAppState = any; // Just a sample response object interface ISampleThunkResponse {

我已经按照官方的Redux指南创建了thunk动作创建者,这样我就可以在react组件中使用绑定动作。但是,我的组件无法识别函数返回的承诺,因此我不能使用
then
,这也意味着我无权访问函数的返回值

以下是我的action creator代码示例:

// Temp State for now, not important
type IAppState = any;

// Just a sample response object
interface ISampleThunkResponse {
  text: string;
  active: boolean;
}

// Thunk action
export function sampleThunk(
  text: string
): ThunkAction<Promise<ISampleThunkResponse>, IAppState, null, Action<string>> {
  return async (dispatch, getState): Promise<ISampleThunkResponse> => {
    const apiResponse = await Promise.resolve({ text, active: true });
    dispatch({ payload: apiResponse, type: 'SOME_TYPE' });
    return apiResponse;
  };
}
我希望redux文档中也提供了关键部分,即具有
ConnectedProps
类型,以便能够包装
连接器

我还将功能性的
mapDispatchToProps
转换为对象版本,但就键入而言,这并没有真正改变任何东西


更大的变化是必须将我的connect调用移动到一个变量中,以便使它可用于我的
ConnectedProps

ISampleCompProps
声明
sampleThunkConnect
是错误的

thunk action creator+thunk函数的定义方式与传递到组件的绑定道具的类型之间存在差异

最终,
this.props.sampleThunkConnect
看起来像
(text:string)=>Promise
,因为调度thunk会返回thunk函数返回的结果。但是,您当前使用的是thunk action创建者本身的实际类型,因此导致代码中断

connect
的React-Redux类型有一些奇特的内部类型,可以将thunk“解析为其返回类型。根据和文章中的示例,您可以重用其中一种类型来提取“props from
connect
”的类型,并让TS自己了解细节


另外,我强烈建议您使用,而不是自己将其作为函数编写。

看看您提供的要点,我需要采用的模式几乎是颠倒的。我认为我编写React组件的方式已经过时了。在要点中,他们创建了
连接器
,然后用它装饰组件。希望这样做不会对我的代码产生任何影响。我试试看。作为补充说明,您还建议使用对象速记进行mapDispatch,因此在我的代码中这似乎也过时了。我会更新你的评论,做一些重构,然后回来给你一个例子,看看是否一切都好。谢谢好的,我已经重构了我的代码,更新了问题,并在问题解决后关闭了它!谢谢你,马克!嘿,我有一个快速跟进的问题,所以一切正常,除了需要将连接的动作创建者作为道具传递到子组件的情况。因此,我将父组件与3-4个动作创建者连接起来,但其中一个子组件只需要
doFetchAppConnected
。我如何在我的子组件道具中键入此内容?我不能简单地做
doFetchAppConnected:,因为原始问题。有办法解决这个问题吗?类似于
ReturnType
?好吧,我想出来了,下面是你的方法:
从'react redux'导入{InferThunkActionCreatorType}
导出类型IDoFetchApp=InferThunkActionCreatorType
doFetchAppConnected:IDoFetchApp
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { sampleThunk } from './sampleThunk';
import * as React from 'react';

export interface ISampleCompProps {
  sampleThunkConnect?: typeof sampleThunk;
}

export function SampleComp(props: ISampleCompProps) {
  const {
    sampleThunkConnect
  } = props;

  function handleClick() {
    // HERE IS THE ERROR
    // Property 'then' does not exist on type 'ThunkAction<Promise<ISampleThunkResponse>, any, null, Action<string>>'.
    sampleThunkConnect('SAMPLE TEXT').then(value => console.log(value));
  }
  return (
    <div onClick={handleClick}>Whatever...</div>
  );
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    {
      sampleThunkConnect: sampleThunk,
    },
    dispatch
  );
}

export default connect<(
  null,
  mapDispatchToProps
)(SampleComp);
import { connect } from 'react-redux';
import { sampleThunk } from './sampleThunk';
import * as React from 'react';
import { InferableComponentEnhancerWithProps } from 'react-redux';

// Typing
type ConnectedProps<T> = T extends InferableComponentEnhancerWithProps<infer Props, infer _>
      ? Props
      : never;

type PropsFromRedux = ConnectedProps<typeof connector>;

export interface ISampleCompOwnProps {
  uuid: string;
}

type ISampleCompProps = ISampleCompOwnProps & PropsFromRedux;

// Temp State for now, not important
type IAppState = any;

// Redux Connect
const mapDispatchToProps = {
  sampleThunkConnect: sampleThunk,
};

const mapStateToProps = (state: IAppState) => ({
  someStateKey: state.someStateKey,
});

const connector = connect(
  mapStateToProps,
  mapDispatchToProps
);

// tslint:disable-next-line function-name
export function SampleComp(props: ISampleCompProps) {
  const {
    sampleThunkConnect
  } = props;

  function handleClick() {
    // Everything is working now!
    sampleThunkConnect('SAMPLE TEXT').then(value => console.log(value));
  }
  return (
    <div onClick={handleClick}>Whatever...</div>
  );
}

export default connector(SampleComp);