首页 > 解决方案 > Typescript Redux 使用 connect 编译错误(组件与签名不匹配)

问题描述

我有一个无法编译的 typescript react/redux 组件。我有其他几乎完全相同的组件并且可以编译。我需要了解为什么这个没有编译。

非编译组件源(完整):

import * as React from 'react';
import { connect } from 'react-redux';
import { ApplicationState } from '../store';

interface ToastProps {
    messages: string[]
}

 interface FadeState {
    visible: boolean
}

class ToastBar extends React.Component<ToastProps, FadeState> {
    public render() {
        if (this.props.messages.length > 0) {
            this.state = { visible: true };
        } else {
            this.state = { visible: false };
        }
        let key = 0;
        return <div id="toastbar" className={this.state.visible ? 'show' : ''}>
            {this.props.messages.map(function (listValue) {
                return <p key={++key}>{listValue}</p>;
            })}            
        </div>;
    }
}

const mapStateToProps = (state: ApplicationState, ownProps?: ToastProps) => ({
    messages: state ? state.toastMessages.messages : []
});

export default connect(mapStateToProps, {}, null, { pure: false })(ToastBar);

我从 IDE 和运行 npm run-script build 收到此错误消息:

(9,82):“typeof ToastBar”类型的参数不可分配给“ComponentType>”类型的参数。类型“typeof ToastBar”不可分配给类型“StatelessComponent>”。类型 'typeof ToastBar' 不提供签名匹配 '(props: Shared<{ messages: String[]; }, ToastProps> & { children?: ReactNode; }, context?: any): ReactElement | 无效的'。

这是另一个编译良好的组件:

import * as UserStore from '../store/UserManagement';
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { ApplicationState } from '../store';
import { connect } from 'react-redux';
import { User, UserRole } from '../model/User';
import { UserEditDialog } from './UserEditDialog';

interface UserMgmtState {
    isLoading: boolean;
    users: User[];
    currentUser: User;
}

interface UserEditState {
    editingUser: User | null;
}

type DispatchProps = typeof UserStore.actionCreators;
type UserManagementProps = UserMgmtState & DispatchProps & RouteComponentProps<{}>;

class UserManagement extends React.Component<UserManagementProps, UserEditState> {

    componentWillMount() {
        // snipped
    }

    editUser(user: User) {
        this.setState({
            editingUser: user
        }); 
    }

    stopEditingUser() {
        this.setState({
            editingUser: null
        });
    }

    deleteUser(user: User) {
        if (confirm('Delete ' + user.fullName + '. Are you sure?'))
            this.props.deleteUser(user.name);
    }

    userIsCurrentUser(user: User): boolean {
        return this.props.currentUser.name == user.name;
    }

    saveUserEdit(user: User) {
        this.props.updateUser(user);
        this.setState({
            editingUser: null
        });
    }

    displayRoles(roles: UserRole[]): string {
        return roles.join(', ');
    }

    renderUsersTable(): any {
        if (this.props.isLoading) {
            return <div>Loading users</div>;
        }
        else {
            return <div>
                <!-- snipped -->
             </div>;
        }
    }

    public render() {
        return <div>
            <h1>User Management</h1>
            {this.renderUsersTable()}
        </div>;
    }
}

const mapStateToProps = (state: ApplicationState, ownProps?: UserMgmtState) => ({
    isLoading: state ? state.userManagement.isLoading : false,
    users: state ? state.userManagement.users : [],
    currentUser: state ? state.loggedInUser.currentUser : null
});

export default connect(
    mapStateToProps, // Selects which state properties are merged into the component's props
    UserStore.actionCreators // Selects which action creators are merged into the component's props
)(UserManagement);

为什么 UserManagement 编译,而 Toastbar 不编译?我真的很迷这里...

标签: typescriptreact-redux

解决方案


问题是 state.toastMessages.messages 属性的类型是 String[],而 ToastProps.messages 属性的类型是 string[]

这些是不同的类型,因此 TypeScript 不认为 mapStateToProps 方法的结果与 ToastProps 接口具有相同的类型。

万一其他人有类似的问题并想知道如何排除故障:为了解决这个问题,我将单行 mapStateToProps 方法更改为定义并返回结果的多行方法,然后编译问题就出现了。一旦我知道 mapStateToProps 的输出类型不兼容,我就检查了 state.toastMessages.messages 的类型并发现了问题


推荐阅读