Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking react-router-dom for useHistory hook causes the following error - TS2698: Spread types may only be created from object types

I am trying to mock react-router-dom in one of my test cases so that the useHistory hook will function in my tests. I decide to use jest.mock to mock the entire module, and jest.requireActual to preserve the other properties that I may not want to mock.

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  useHistory: () => ({
    location: {
      pathname: '/list',
    },
  }),
}));

This is actually derived from one of the highly rated solutions to the following question: How to mock useHistory hook in jest?

However, the TypeScript compiler is flagging the following error on the following line ...jest.requireActual('react-router-dom'),

TS2698: Spread types may only be created from object types.

Interestingly, I only face this issue after updating jest and ts-jest to the latest versions (jest v26). I do not face any of these issues when I was using jest 24.x.x.

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

Does anyone know how to solve this issue for the latest jest versions?

like image 848
wentjun Avatar asked Jul 07 '20 12:07

wentjun


1 Answers

jest.requireActual returns unknown type that cannot be spread.

A correct type is:

import * as ReactRouterDom from 'react-router-dom';

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom') as typeof ReactRouterDom,
  useHistory: ...,
}));

A quick fix is any:

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom') as any,
  useHistory: ...,
}));

It's acceptable because it doesn't impair type safety in this case.

Since react-router-dom is ES module, a more correct way to mock it is:

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom') as any,
  __esModule: true,
  useHistory: ...,
}));
like image 85
Estus Flask Avatar answered Oct 06 '22 07:10

Estus Flask