使用Jest Mock React函数组件时VSCode报TS2786错误求助
我在测试中创建了一个假组件,用来跟踪它是否被正确调用,测试能正常运行,但Visual Studio Code始终报以下错误:MockedComponent' cannot be used as a JSX component. Its instance type 'Element' is not a valid JSX element.ts(2786)
测试代码(my-test.test.tsx)
test('should do something', () => { const MockedComponent = jest.fn((props: SomeProps) => { return <div>{props.foo}</div> }) render( <div> <MockedComponent foo="bar" /> </div> ) expect(MockedComponent).toHaveBeenCalled() })
VSCode错误信息
MockedComponent' cannot be used as a JSX component. Its instance type 'Element' is not a valid JSX element.ts(2786)
错误原因
TypeScript对JSX组件的类型有明确要求:合法的JSX组件要么是继承React.Component的类组件,要么是返回ReactElement或null的函数组件。
你用jest.fn()创建的MockedComponent,TypeScript会自动推断它的类型为jest.Mock,而非标准的React函数组件类型。虽然运行时它能正常返回元素,但TS的类型检查不认可这个Mock类型,所以抛出了报错。
解决办法
给MockedComponent手动指定正确的React函数组件类型即可,常用两种方式:
方式1:显式声明组件类型
引入React的FC(Function Component)类型并标注:
import type { FC } from 'react'; test('should do something', () => { const MockedComponent: FC<SomeProps> = jest.fn((props) => { return <div>{props.foo}</div> }) render( <div> <MockedComponent foo="bar" /> </div> ) expect(MockedComponent).toHaveBeenCalled() })
方式2:类型断言处理(适用于外部组件Mock)
如果是Mock外部组件,可以用类型断言让TS识别为合法组件:
jest.mock('./RealComponent', () => { return jest.fn((props: SomeProps) => <div>{props.foo}</div>) as React.FC<SomeProps>; });
如果遇到类型不兼容的情况,也可以用as unknown as React.FC<SomeProps>来强制转换。
补充说明
测试能正常运行是因为Jest在运行时会忽略TypeScript的类型检查,直接执行代码逻辑;但VSCode的TS语言服务会严格校验类型匹配,所以才会出现“报错但测试能跑”的矛盾情况。
内容的提问来源于stack exchange,提问作者Matheus Solha

