【发布时间】:2018-09-02 01:25:54
【问题描述】:
我正在尝试将使用 Enzyme 的 Jest 测试转换为 TypeScript,但遇到了一种我不确定如何处理的特殊情况。基本上,我试图调用一个作为道具传递给子组件的函数。我看到的错误是:
spec/javascript/_common/components/sidebar_spec.tsx:85:5 - 错误 TS2349:
Cannot invoke an expression whose type lacks a call signature. Type '{}' has no compatible call signatures.
85 component.find(Link).at(0).prop('onNavigate')();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如何克服这个错误?不确定它是否有帮助,但更多的测试背景:
it('does not hide the sidebar after a link is clicked', () => {
const component = shallow(<Sidebar />);
component.find(Link).at(0).prop('onNavigate')();
component.update();
expect(component.find(Link)).toHaveLength(3);
});
还有来自Sidebar 组件的一段代码:
class Sidebar extends React.Component<any, any> {
...
hideIfMobile() {
const {mobile} = this.state;
if (mobile) { this.setState({visible: false}); }
}
render() {
const {visible} = this.state;
if (!visible) {
return (
<div className='sidebar sidebar--hidden'>
{this.sidebarToggle()}
</div>
);
}
const linkProps = {
baseClass: 'sidebar__link',
onNavigate: this.hideIfMobile,
};
return (
<div className='sidebar sidebar--visible'>
<h2 className='sidebar__header'>{'Menu'}{this.sidebarToggle()}</h2>
<hr className='sidebar__divider' />
<Link to='root' {...linkProps}><h2>{'FOCUS'}</h2></Link>
<Link to='tasks' {...linkProps}><h2>{'ALL TASKS'}</h2></Link>
<Link to='timeframes' {...linkProps}><h2>{'TIMEFRAMES'}</h2></Link>
</div>
);
}
}
Link 组件被包裹在react-redux:
import {connect} from 'react-redux';
import Link from 'src/route/components/link';
import {getRouteName} from 'src/route/selectors';
import {setRoute} from 'src/route/action_creators';
function mapStateToProps(state) {
return {routeName: getRouteName(state)};
}
export default connect(mapStateToProps, {setRoute})(Link);
和实际的组件:
class Link extends React.Component<any, any> {
navigate(event) {
event.preventDefault();
const {onNavigate, params, setRoute, to} = this.props;
setRoute({name: to, ...params});
if (onNavigate) { onNavigate(); }
}
path() {
const {params, to} = this.props;
const pathParams = mapValues(params, value => value.toString());
return findRoute(to).toPath(pathParams);
}
className() {
const {baseClass, className, to, routeName} = this.props;
return classnames(
baseClass,
{[`${baseClass}--active`]: baseClass && routeName === to},
className,
);
}
render() {
const {children} = this.props;
return (
<a
href={this.path()}
className={this.className()}
onClick={this.navigate}
>
{children}
</a>
);
}
}
【问题讨论】:
-
请将
Link的定义添加到问题中。当我将其定义为class Link extends React.Component<{baseClass: string, onNavigate: () => void}, {}> {}时,我没有收到错误消息。 -
已添加。在这种情况下,我也使用
class语法。但是,它也封装在react-redux容器中。 -
connect调用生成的组件的 props 类型推断可能有问题。为了重现这个问题,我需要知道getRouteName和setRoute的类型。或者您可以自行调查,首先将鼠标悬停在export default connect...中的default上,查看类型是什么。 -
@MattMcCutchen 不确定
getRouteName和setRoute在这种情况下是否相关。当我完全删除它们时,我仍然看到相同的错误。当我删除动作创建者和状态时,connect调用的返回是(alias) connect(): InferableComponentEnhancerWithProps<DispatchProp<AnyAction>, {}> (+11 overloads)。
标签: reactjs typescript jestjs enzyme