jest-dom: TS error when using vitest globals and @testing-library/jest-dom

  • @testing-library/jest-dom version: 5.16.1
  • node version: 14.17.0
  • yarn version: 1.22.17
  • @testing-library/react version: 12.1.2

I am using vitest instead of jest for testing a React component lib in a monorepo. I am using @testing-library/jest-dom and @testing-library/react and both happily work with vitest.

However, when type checking my code I am seeing a clash between @types/jest and vitest. The @types/jest dependency seems to have been pulled in by @testing-library/jest-dom.

../node_modules/@types/jest/index.d.ts:34:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: test, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach

34 declare var beforeAll: jest.Lifecycle;
   ~~~~~~~

  ../node_modules/vitest/global.d.ts:1:1
    1 declare global {
      ~~~~~~~
    Conflicts are in this file.

../node_modules/vitest/global.d.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: test, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach

1 declare global {
  ~~~~~~~

  ../node_modules/@types/jest/index.d.ts:34:1
    34 declare var beforeAll: jest.Lifecycle;
       ~~~~~~~
    Conflicts are in this file.


Found 2 errors.

It would be great to have a workaround for this issue so the jest types can be removed or ignored.

To reproduce this issue clone the following project (notice it uses a branch called yarn):

https://github.com/robcaldecott/pnpm-vite-monorepo-example/tree/yarn

To see the error:

yarn install
cd components
yarn build

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 48
  • Comments: 25 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Hi. How about providing @testing-library/vitest-dom ? Since the release of Vitest, the number of downloads of Vitest has increased. I think the official support for using Testing Library with Vitest makes us very happy and we don’t have to add ad-hoc solutions.

@gnapse is there any possibility to remove /// <reference types="jest" /> from library types and make @types/jest a peerDependency?

Anyway, I found a slightly less hacky workaround 💯 :

setupTests.ts (file which goes to test.setupFiles in vite.config.ts)

import '@testing-library/jest-dom/extend-expect';

global.d.ts (file placed in root or inside src directory)

/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-unused-vars */
import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers';

declare global {
  namespace jest {
    type Matchers<R = void, T = {}> = TestingLibraryMatchers<
      typeof expect.stringContaining,
      R
    >;
  }
}

tsconfig.json

{
  "compilerOptions": {
   ...
    "types": ["node", "vite/client", "vitest/globals"],
  },
}

Tried the workaround above, but had to tweak one thing. In global.d.ts I had to write this instead:

import type { TestingLibraryMatchers } from "@testing-library/jest-dom/matchers";

declare global {
  namespace jest {
    interface Matchers<R = void>
      extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
  }
}

Maybe the inverse would be a cleaner solution, where we provide jest.d.ts and vitest.d.ts

I like this approach as well.

For now, I am using a workaround with pnpm patch, creating this diff to empty the definitions in @types/testing-library__jest-dom/index.d.ts:

diff --git a/index.d.ts b/index.d.ts
index 43ba6b7fe458e77d152fe0b2f7afeac05d8fc563..dfa540aa7d1ab8c78c31104d3210eee3c33a94c0 100755
--- a/index.d.ts
+++ b/index.d.ts
@@ -7,12 +7,9 @@
 // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
 // Minimum TypeScript Version: 4.3
 
-/// <reference types="jest" />
+// NOTE: these definitions are left blank, to support using Testing Library Jest matchers with
+// Vitest, without having to use Jest's global types (for `expect`, etc).
 
-import { TestingLibraryMatchers } from './matchers';
+// Vitest's `expect` type is instead extended in `src/setupTests.ts`.
 
-declare global {
-    namespace jest {
-        interface Matchers<R = void, T = {}> extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
-    }
-}
+// For more context, see https://github.com/testing-library/jest-dom/issues/427

In patches/@types__testing-library__jest-dom@5.14.5.patch, with this in package.json:

"pnpm": {
  "patchedDependencies": {
    "@types/testing-library__jest-dom@5.14.5": "patches/@types__testing-library__jest-dom@5.14.5.patch"
  }
}

Paired with this in my Vitest setup file: https://github.com/testing-library/jest-dom/issues/439#issuecomment-1087504347

import matchers, {
  TestingLibraryMatchers,
} from '@testing-library/jest-dom/matchers';

declare global {
  namespace Vi {
    interface JestAssertion<T = any>
      extends jest.Matchers<void, T>,
        TestingLibraryMatchers<T, void> {}
  }
}

expect.extend(matchers);

I made a simple solution to fix this issue: https://github.com/zoontek/types-testing-library-vitest-dom

Installation (yarn)

"resolutions": {
  "@types/testing-library__jest-dom": "github:zoontek/types-testing-library-vitest-dom"
}

Installation (npm)

"overrides": {
  "@types/testing-library__jest-dom": "github:zoontek/types-testing-library-vitest-dom"
}

Test setup file

import matchers from "@testing-library/jest-dom/matchers";
import { expect } from "vitest";

expect.extend(matchers);

🎉 This issue has been resolved in version 6.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Solution for pnpm users:

Add this to your package.json:

  "pnpm": {
    "patchedDependencies": {
      "@types/testing-library__jest-dom@5.14.5": "patches/@types__testing-library__jest-dom@5.14.5.patch"
    }
  }

Now, create a file patches/@types__testing-library__jest-dom@5.14.5.patch with the following contents:

diff --git a/index.d.ts b/index.d.ts
index 43ba6b7fe458e77d152fe0b2f7afeac05d8fc563..3bf91587abf21f15ac166bcae1f5a59b23884b87 100755
--- a/index.d.ts
+++ b/index.d.ts
@@ -7,7 +7,7 @@
 // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
 // Minimum TypeScript Version: 4.3
 
-/// <reference types="jest" />
+// See https://github.com/testing-library/jest-dom/issues/427 for reference
 
 import { TestingLibraryMatchers } from './matchers';

Save both and run pnpm i.

Not sure if this is the correct solution but adding "skipLibCheck": true, in my tsconfig.json fixed it.

Another solution if you don’t mind to install a new package is to install vitest-dom. no hack or workaround and it works straightforward with pnpm too. It is not part of testing-library though.

Do you have any updates on the status of this issue? For now, the approach I’ve followed is the one mentioned into another issue (which targets the latest version of Vite)

I don’t think making a new package is worth the cognitive/maintenance overhead when we could just make this package more framework agnostic for now.

However, I vaguely remember another maintainer planning on refactoring matchers out of this package. Please let me know if there’s an update on that. I couldn’t find the source, but I don’t want to step on any toes accidentally.

for me, using vitest@0.16.0 and @testing-library/jest-dom@5.16.4 only the solution bellow worked

// global.d.ts
import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers';

type CustomMatchers<R = unknown> = TestingLibraryMatchers<typeof expect.stringContaining, R>;

declare global {
  namespace Vi {
    interface Assertion extends CustomMatchers {}
    interface AsymmetricMatchersContaining extends CustomMatchers {}
  }
}

and using pnpm the code bellow need to be placed in the .npmrc to be able to use the TestingLibraryMatchers types outside node_modules

shamefully-hoist = true

Combining @BPreisner and @airjp73’s solutions, I made a new template to save myself (and others) future time: https://github.com/jsjoeio/react-ts-vitest-template

FWIW this works just fine too. (I tend not to care about throwing errors because they are of limited value in a build step like this)

import fs from 'fs'
import path from 'path'

const typesFile = path.resolve('node_modules/@types/testing-library__jest-dom/index.d.ts')
const encoding = 'utf8'
const strings = {
  search: '/// <reference types="jest" />',
  replace: '// See https://github.com/testing-library/jest-dom/issues/427 for reference',
}

const result = fs
  .readFileSync(typesFile, encoding)
  .replace(strings.search, strings.replace)

fs.writeFileSync(typesFile, result, encoding)

EDIT: my vite.config.js and tsconfig.json for reference. @laruiss ☝️