代码之家  ›  专栏  ›  技术社区  ›  Joon

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

  •  0
  • Joon  · 技术社区  · 8 年前

    我正在构建一个react/redux/typescript应用程序。我连接的组件在VS代码(和Visual Studio)中都显示TypeScript错误,但应用程序编译并运行(webpack成功)。

    我想知道我为什么会看到这个错误,如果可能的话,把它去掉。

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

    “type of UserLogin”类型的参数不可分配给 “Component<{}>”类型的参数。类型“typeof UserLogin”不是 可分配给“StatelessComponent<{}>”类型。 类型“typeof UserLogin”不提供与签名匹配的项(props:{children?:ReactNode;},上下文?:any):反应元素<any> |空'

    以下是完整的适用组件代码:

    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;
    }
    

    我正在使用TypeScript3.0.1

    my 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 回复  |  直到 8 年前
        1
  •  1
  •   Matt McCutchen    8 年前

    我想我发现了问题 React version 15 typings 期待 props 组件类构造函数的参数是可选的,即。, constructor(props?: LoginProps) . 如果我做了改变,那么错误就消失了。我不确定输入是否准确,可以将该参数视为可选参数,但我想解决方法是与它们保持一致。

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

        2
  •  0
  •   Joon    8 年前

    对于其他正在处理typescript/redux和TS-type错误的人,我发现了一个非常好的项目启动程序,它可以创建一个干净的应用程序,并指导您逐步添加组件和容器。通过跟踪它,我能够创建一个没有类型映射错误的应用程序,并且干净地使用lints。

    这是指向回购协议的链接,说明如下: https://github.com/Microsoft/TypeScript-React-Starter

    推荐文章