Javascript Redux+;TypeScript和mapDispatchToProps

Javascript Redux+;TypeScript和mapDispatchToProps,javascript,reactjs,typescript,redux,react-redux,Javascript,Reactjs,Typescript,Redux,React Redux,这应该很容易,但目前我还没有做到,但我觉得这应该是一个简单的解决办法。我目前正在将redux与typescript一起使用,并将redux-thunk用于异步动作创建者 设置很简单。以下是我用于登录的代码: export function requestAuthenticationAsync(email: string, password: string) { return (dispatch: ThunkDispatch<IState, undefined, IAction>

这应该很容易,但目前我还没有做到,但我觉得这应该是一个简单的解决办法。我目前正在将
redux
typescript
一起使用,并将
redux-thunk
用于异步动作创建者

设置很简单。以下是我用于登录的代码:

export function requestAuthenticationAsync(email: string, password: string) {
    return (dispatch: ThunkDispatch<IState, undefined, IAction>): Promise<void> => {
        dispatch(requestAuthentication());

        return postAuthentication(email, password).then((response) => {
            dispatch(receiveAuthentication());

            return response.json();
        }).then((data) => {
            dispatch(receiveUser(data));
        });
    };
}
但是,当我使用
connect
mapDispatchToProps
from
react redux
时,如下所示:

import './Gateway.scss';
import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { requestAuthenticationAsync } from './actions';
import { withRouter } from 'react-router-dom';

const mapDispatchToProps = (dispatch) => {
    return {
        requestAuthenticationAsync: bindActionCreators(requestAuthenicationAsync, dispatch)
    };
};

const mapStateToProps = (state) => {
    return {
        authenticated: state.authentication.authenticated
    };
};

class Gateway extends React.Component<{
    authenticated: boolean;
    requestAuthenticationAsync: typeof requestAuthenticationAsync;
}, {
    email: string;
    password: string;
}> {

    constructor(props) {
        super(props);

        this.state = {
            email: '',
            password: ''
        };
    }

    onGatewaySubmit = (event) => {
        event.preventDefault();

        const { requestAuthenticationAsync } = this.props;
        const { email, password } = this.state;

        requestAuthenticationAsync(email, password).then(() => {
            console.log('done');
        });
    };

    onEmailValueChange = (event) => {

        this.setState({
            email: event.target.value
        });
    };

    onPasswordValueChange = (event) => {
        this.setState({
            password: event.target.value
        });
    };

    render() {
        return (
            <div id='gateway'>
                <form onSubmit={ this.onGatewaySubmit }>
                    <input
                        className='email'
                        onChange={ this.onEmailValueChange }
                        placeholder='email'
                        type='text' />
                    <input
                        className='password'
                        onChange={ this.onPasswordValueChange }
                        placeholder='password'
                        type='password' />
                    <input type='submit' value='Submit' />
                </form>
            </div>
        );
    }
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Gateway));
导入“/Gateway.scss”; 从“React”导入*作为React; 从“redux”导入{bindActionCreators}; 从'react redux'导入{connect}; 从“./actions”导入{requestAuthenticationAsync}; 从“react router dom”导入{withRouter}; const mapDispatchToProps=(调度)=>{ 返回{ requestAuthenticationAsync:bindActionCreators(requestAuthenticationAsync,dispatch) }; }; 常量mapStateToProps=(状态)=>{ 返回{ 已验证:state.authentication.authenticated }; }; 类网关扩展了React.Component{ 建造师(道具){ 超级(道具); 此.state={ 电子邮件:“”, 密码:“” }; } onGatewaySubmit=(事件)=>{ event.preventDefault(); const{requestAuthenticationAsync}=this.props; const{email,password}=this.state; requestAuthenticationAsync(电子邮件、密码)。然后(()=>{ console.log('done'); }); }; onEmailValueChange=(事件)=>{ 这是我的国家({ 电子邮件:event.target.value }); }; onPasswordValueChange=(事件)=>{ 这是我的国家({ 密码:event.target.value }); }; render(){ 返回( ); } } 使用路由器导出默认值(连接(mapStateToProps、mapDispatchToProps)(网关)); 我得到以下错误:

TS2339: Property 'then' does not exist on type '(dispatch: ThunkDispatch<IState, undefined, IAction>) => Promise<void>'.
TS2339:type'(dispatch:ThunkDispatch)=>Promise上不存在属性“then”。

有什么好处?在这种情况下,我如何让TypeScript满意,这样我就可以在
中使用承诺。然后

我想检查一下我理解了什么,因为我不能写评论

如果您像这样在代码的
onGatewaySubmit
函数中调用
requestAuthenticationAsync

requestAuthenticationAsync(email, password).then(() => {
    console.log('done');
});
我觉得您正在调用下面的已调度函数

dispatch(requestAuthenticationAsync)(email, password).then(() => {
  // navigate somewhere
});
不象你写的那样

dispatch(requestAuthenticationAsync('email', 'password')).then(() => {
  // navigate somewhere
});

这可能有点离题,但您能解释一下流程吗?

问题的根本原因是
redux-thunk
是由
redux
执行的中间件,因此它调用函数(thunk)并返回值。然而,TypeScript并没有“意识到”正在发生的情况,所以无法正确地键入它(不需要额外的工作)

redux thunk
包(此时)实际上附带类型定义。然而,它的类型定义有很多重大改进,但没有发布。在3.0版本中,它们将被删除并移动到DefinitelyTyped(可通过
@types/redux-thunk
安装)

但在此之前,您可以自己设置类型。如果需要,则类型定义相对较多

要使用这些文件(在它们以新版本的
redux thunk
或DefinitelyTyped发布之前),您可以使用以下内容创建类型文件(例如:
types.d.ts
):

从“redux”导入{ActionCreatorsMapObject};
从“redux-thunk”导入{ThunkAction};
/**
*中间件改变了Redux行为,因此这里重载
*/
声明模块“redux”{
/**
*bindActionCreators redux函数的重载,返回预期响应
*从恶作剧中
*/
函数bindActionCreators<
通过查看
TActionCreators扩展ActionCreatorsMapObject
,TActionCreators扩展了ActionCreatorsMapObject)

现在应该正确键入
This.props.requestAuthenticationAsync
,以便在组件中使用

onGatewaySubmit = event => {
  event.preventDefault();

  const { requestAuthenticationAsync } = this.props;
  const { email, password } = this.state;

  // Type:
  //   (email: string, password: string) => Promise<void>
  requestAuthenticationAsync(email, password).then(() => {
    console.log("done");
  });
};
onGatewaySubmit=事件=>{
event.preventDefault();
const{requestAuthenticationAsync}=this.props;
const{email,password}=this.state;
//类型:
//(电子邮件:string,密码:string)=>承诺
requestAuthenticationAsync(电子邮件、密码)。然后(()=>{
控制台日志(“完成”);
});
};

这实际上是一个非常简单的解决方案,我一定忽略了。特定道具组件中的类型是错误的

而不是:

requestAuthenticationAsync: typeof requestAuthenticationAsync;
我把它改成:

requestAuthenticationAsync: ReturnType<requestAuthenticationAsync>;
requestAuthenticationAsync:ReturnType;
这能够捕获
(email:string,password:string)=>Promise
类型,编译器停止抱怨,一切正常

requestAuthenticationAsync: ReturnType<requestAuthenticationAsync>;