连接的Redux组件上的Typescript验证错误

时间:2018-08-06 16:27:05

标签: typescript react-redux

我正在构建一个react / redux / typescript应用程序。我连接的所有组件在VS Code(和Visual Studio)中均显示TypeScript错误,但该应用程序可以编译并正常运行(Webpack成功)。

我想了解为什么我会看到此错误,并尽可能消除它。

在我所有连接的组件中,当我使用connect函数导出默认类型时,我看到一条警告,提示我导出的组件不符合特定的接口。这是完整错误消息的示例:

  

[ts]类型'typeof UserLogin'的参数不可分配给   类型为“ Component <{}>”的参数。类型“ typeof UserLogin”不是   可分配给类型'StatelessComponent <{}>'。       类型'typeof UserLogin'不提供签名'(props:{children ?: ReactNode;},context ?: any)的匹配:ReactElement   |空”

以下是适用的组件代码全文:

import { connect, Dispatch } from 'react-redux';
import * as React from 'react';
import { UserRole } from '../model/User';
import { RouteComponentProps } from 'react-router-dom';
import * as LoginStore from '../store/LoggedInUser';
import { ApplicationState } from 'ClientApp/store';

type DispatchProps = typeof LoginStore.actionCreators;
type LoginProps = DispatchProps & RouteComponentProps<{}>;

interface LoginFields {
    userName: string,
    password: string
}

class UserLogin extends React.Component<LoginProps, LoginFields> {

    constructor(props: LoginProps) {
        super(props);

        this.state = {
            userName: '',
            password: ''
        }

        this.userNameChange = this.userNameChange.bind(this);
        this.pwdChange = this.pwdChange.bind(this);
    }

    userNameChange(e: React.ChangeEvent<HTMLInputElement>) {
        this.setState({ userName: e.target.value, password: this.state.password });
    }

    pwdChange(e: React.ChangeEvent<HTMLInputElement>) {
        this.setState({ userName: this.state.userName, password: e.target.value });
    }

    public render() {
        return <div>
            <h1>User Login</h1>
            <div className="form-group">
                <label htmlFor="exampleInputEmail1">Email address</label>
                <input type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
                    placeholder="Enter email" value={this.state.userName} onChange={this.userNameChange} />
            </div>
            <div className="form-group">
                <label htmlFor="exampleInputPassword1">Password</label>
                <input type="password" className="form-control" id="exampleInputPassword1" placeholder="Password"
                    value={this.state.password} onChange={this.pwdChange} />
            </div>
            <button type="submit" className="btn btn-primary"
                onClick={() => this.props.login(this.state.userName, this.state.password)}>Login</button>
        </div>;
    }
}

// Wire up the React component to the Redux store
export default connect(
    null, LoginStore.actionCreators
)(UserLogin) as typeof UserLogin;

这是动作创建者的定义:

export const actionCreators = {
    login: (userName: string, pass: string): AppThunkAction<Action> => (dispatch, getState) =>
    {
        var loggedIn = false;

        axios.post('api/Auth/', {
            UserName: userName,
            Password: pass
        }).then(function (response) {
            let tokenEncoded = response.data.token;
            let tokenDecoder = new JwtHelper();
            let token = tokenDecoder.decodeToken(tokenEncoded);
            let usr = new User(userName, JSON.parse(token.userRoles), token.fullName, tokenEncoded);
            dispatch(<LoginUserAction>{ type: 'LOGIN_USER', user: usr });
            dispatch(<RouterAction>routeThings.push('/'));            
        }).catch(function (error) {
            let message = 'Login failed: ';
            if (error.message.indexOf('401') > 0) {
                message += ' invalid username or password';
            } else {
                message += error.message;
            }
            toasting.actionCreators.toast(message, dispatch);
        });
    },
    logout: () => <Action>{ type: 'LOGOUT_USER' }
};

AppThunk的定义:

export interface AppThunkAction<TAction> {
    (dispatch: (action: TAction) => void, getState: () => ApplicationState): void;
}

我正在使用TypeScript 3.0.1

我的package.json中可能相关的版本:

"@types/react": "15.0.35",
"@types/react-dom": "15.5.1",
"@types/react-hot-loader": "3.0.3",
"@types/react-redux": "4.4.45",
"@types/react-router": "4.0.12",
"@types/react-router-dom": "4.0.5",
"@types/react-router-redux": "5.0.3",

"react": "15.6.1",
"react-dom": "15.6.1",
"react-hot-loader": "3.0.0-beta.7",
"react-redux": "5.0.5",
"react-router-dom": "4.1.1",
"react-router-redux": "^5.0.0-alpha.6",
"redux": "3.7.1",
"redux-thunk": "2.2.0",

错误的屏幕截图: enter image description here

2 个答案:

答案 0 :(得分:1)

我认为我发现了问题:React version 15 typings期望组件类构造函数的props参数是可选的,即constructor(props?: LoginProps)。如果我进行更改,则错误会消失。我不确定类型是否正确,可以认为该参数是可选的,但我认为解决方案应与它们保持一致。

FWIW,我的印象也是as typeof UserLogin没有意义。我无法解释为什么因为TypeScript会删除类型信息,所以删除它会改变运行时行为。

答案 1 :(得分:0)

对于其他在打字稿/ redux和TS类型错误方面苦苦挣扎的人来说,我找到了一个非常好的项目启动器,它创建了一个干净的应用程序,并引导您逐步添加组件和容器。通过遵循它,我能够创建一个没有类型映射错误并且干净整洁的应用程序。

这是带有说明的仓库的链接:https://github.com/Microsoft/TypeScript-React-Starter