为 useHistory 钩子模拟 react-router-dom 会导致以下错误 - TS2698: Spread types may only be created from object ty
Posted
技术标签:
【中文标题】为 useHistory 钩子模拟 react-router-dom 会导致以下错误 - TS2698: Spread types may only be created from object types【英文标题】:Mocking react-router-dom for useHistory hook causes the following error - TS2698: Spread types may only be created from object types 【发布时间】:2020-10-27 16:35:46 【问题描述】:我试图在我的一个测试用例中模拟react-router-dom
,以便useHistory
挂钩将在我的测试中起作用。我决定使用jest.mock
来模拟整个模块,并使用jest.requireActual
来保留我可能不想模拟的其他属性。
jest.mock('react-router-dom', () => (
...jest.requireActual('react-router-dom'),
useHistory: () => (
location:
pathname: '/list',
,
),
));
这实际上源自对以下问题的高度评价的解决方案之一:How to mock useHistory hook in jest?
但是,TypeScript 编译器在以下行标记以下错误 ...jest.requireActual('react-router-dom'),
TS2698:传播类型只能从对象类型创建。
有趣的是,我只有在将 jest 和 ts-jest 更新到最新版本(jest v26)后才会遇到这个问题。我在使用 jest 24.x.x 时没有遇到任何这些问题。
"@types/jest": "^26.0.4",
"jest": "^26.1.0",
"ts-jest": "^26.1.1",
有人知道如何为最新的 jest 版本解决这个问题吗?
【问题讨论】:
jest.requireActual('react-router-dom')
返回了什么?
应该是“react-router-dom”包中的其他属性/方法?我这样做的目的是只模拟 useHistory
钩子,而不是整个包。
【参考方案1】:
jest.requireActual
返回的unknown
类型不能传播。
正确的类型是:
import * as ReactRouterDom from 'react-router-dom';
jest.mock('react-router-dom', () => (
...jest.requireActual('react-router-dom') as typeof ReactRouterDom,
useHistory: ...,
));
快速解决方法是any
:
jest.mock('react-router-dom', () => (
...jest.requireActual('react-router-dom') as any,
useHistory: ...,
));
这是可以接受的,因为在这种情况下它不会损害类型安全。
由于react-router-dom
是ES模块,更正确的模拟方式是:
jest.mock('react-router-dom', () => (
...jest.requireActual('react-router-dom') as any,
__esModule: true,
useHistory: ...,
));
【讨论】:
谢谢!这解决了我的问题。知道为什么这个错误只会出现在 jest 26 上吗? 另外一点要补充的是,对于那些使用默认推荐的eslint设置的人,你需要在ReactRouterDom
类型断言之上添加// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
,尽管eslint告诉我们不需要断言类型。
可能您使用了没有此行为的旧 TS 版本,或者使用了具有不同类型的另一个 Jest 设置,还有第三方 @types/jest
。没错,我总是默认禁用此规则。
requireActual
is generic,所以另一种选择是:...jest.requireActual<typeof ReactRouterDom>("react-router-dom")
。
我可以确认@JonathanReyes 的解决方案同样有效 :)以上是关于为 useHistory 钩子模拟 react-router-dom 会导致以下错误 - TS2698: Spread types may only be created from object ty的主要内容,如果未能解决你的问题,请参考以下文章
useHistory react-router-dom 无效的钩子调用
模拟 useHistory 并期望 toBeCalledWith