更新到react addons测试实用程序的最新.d.ts定义破坏了我们测试代码的编译。在该功能中:
import * as TestUtils from 'react-addons-test-utils';
import MyReactComponent from 'blabla'
let buildComponent = () => {
const root = TestUtils.renderIntoDocument(<MyReactComponent/>);
return TestUtils.findRenderedComponentWithType(root, MyReactComponent);
}
将root
传递给此处的最后一个函数会导致error TS2345: Argument of type 'Component<any, {}> | Element | void' is not assignable to parameter of type 'Component<any, any>'.
很好,我可以投:
let buildComponent = () => {
const root = TestUtils.renderIntoDocument(<MyReactComponent/>);
return TestUtils.findRenderedComponentWithType(root as React.Component<any, any>, MyReactComponent);
}
但现在通过最后一行的MyReactComponent
会导致error TS2345: Argument of type 'typeof MyReactComponent' is not assignable to parameter of type 'ComponentClass<{}> & (new () => MyReactComponent) & (new () => { props: any; })'.
显然,它期望ClassType<any, T, C>
,而C extends ComponentClass<{}>
,不知何故,我的class MyReactComponent extends React.Component<IMyReactComponentProps, IMyReactComponentState>
不符合要求,但我不明白。
不可分配给"组件"类型的参数
这意味着root
的类型应该是React.Component<any,any>
。这意味着TestUtils.renderIntoDocument
的签名可能是错误的。
破解:
import * as TestUtils from 'react-addons-test-utils';
import MyReactComponent from 'blabla'
let buildComponent = () => {
const root: React.Component<any, any> = TestUtils.renderIntoDocument(<MyReactComponent/>) as any;
return TestUtils.findRenderedComponentWithType(root, MyReactComponent);
}
更多
注意,需要使用any
,因为返回值和所需返回值之间没有简单的结构关系。看见https://basarat.gitbooks.io/typescript/content/docs/types/type-assertion.html详细信息。
也有同样的问题,以下帮助:
TestUtils.findRenderedComponentWithType(root as React.Component<any, any>, MyReactComponent as any);
考虑到React和定义文件的突破性变化和流动性,我们可能会通过抽象使用显式类型帮助器下的第三方方法来为它提供一些帮助(并可能简化对未来变化的修复)。我们在当前定义中失去了一些"灵活性",但如果知道renderIntoDocument
的返回类型和findRenderedComponentWithType
的参数类型(例如),我们可以定义这样的包装器:
function renderIntoDocument (reactEl: React.ReactElement<{}>) {
return TestUtils.renderIntoDocument(reactEl) as React.Component<{}, {}>
}
function findRenderedComponentWithType(root: React.Component<{}, {}>, type: React.ComponentClass<{}>): React.Component<{}, {}> {
return TestUtils.findRenderedComponentWithType(root, type as any)
}
let buildComponent = () => {
const root = renderIntoDocument(<MyReactComponent/>);
return findRenderedComponentWithType(root, MyReactComponent);
}