首页 > 解决方案 > 为 useHistory 钩子模拟 react-router-dom 会导致以下错误 - TS2698: Spread types may only be created from object types

问题描述

我试图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.xx 时,我没有遇到任何这些问题

"@types/jest": "^26.0.4",
"jest": "^26.1.0",
"ts-jest": "^26.1.1",

有谁知道如何为最新的笑话版本解决这个问题?

标签: reactjstypescriptreact-routerjestjsreact-hooks

解决方案


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: ...,
}));

推荐阅读