@testing-library/jest-dom version: 7.0.1
node version: 24.19.0
jest (or vitest) version: vitest 5.0.0
npm (or yarn) version: pnpm 11.21.0
typescript version: 7.0.2 (same result with 5.9)
Relevant code or config:
types/vitest.d.ts as shipped in 7.0.1 (and on main):
import 'vitest'
import {type TestingLibraryMatchers} from './matchers'
declare module 'vitest' {
interface Assertion<T = any>
extends TestingLibraryMatchers<any, T> {}
interface AsymmetricMatchersContaining
extends TestingLibraryMatchers<any, any> {}
}
Vitest 5.0.0 changed the interface this augments. Assertion now takes the return type first and the received type second (vitest/dist/chunks/config.d.*.d.ts):
interface Assertion<
R extends void | Promise<void> = void,
T = unknown
> extends VitestAssertion<Chai.Assertion, R, T>, JestAssertion<R, T>, ChaiMockAssertion<R, T>, Matchers<R, T> { … }
What you did:
Upgraded a Vitest 4.1.11 project (vitest, @vitest/ui, @vitest/coverage-v8) to 5.0.0, with import '@testing-library/jest-dom/vitest' in the setup file, and ran tsc.
What happened:
Every jest-dom matcher disappears from the assertion type. 1,203 errors of the form:
src/…/status-cell.test.tsx(53,38): error TS2339: Property 'toBeInTheDocument' does not exist on type 'Assertion<void, HTMLElement>'.
src/…/status-cell.test.tsx(116,7): error TS2339: Property 'toBeDisabled' does not exist on type 'Assertion<void, HTMLElement>'.
The runtime side is fine — expect.extend still registers the matchers and the tests pass. Only the types are gone.
Cause: TypeScript only merges interface declarations whose type parameter lists are identical. jest-dom's Assertion<T = any> (one parameter) no longer matches Vitest's Assertion<R, T> (two), so the augmentation is dropped. The mismatch itself is reported inside node_modules (TS2428 "All declarations of 'Assertion' must have identical type parameters"), which skipLibCheck: true hides — so the only visible symptom is the matchers vanishing.
Reproduction:
mkdir repro && cd repro && npm init -y
npm i -D vitest@5.0.0 typescript @testing-library/jest-dom@7.0.1 @testing-library/dom
cat > a.test.ts <<'TS'
import '@testing-library/jest-dom/vitest'
import { expect, it } from 'vitest'
it('x', () => { expect(document.body).toBeInTheDocument() })
TS
npx tsc --noEmit --skipLibCheck --moduleResolution bundler --module esnext --target es2022 --lib es2022,dom a.test.ts
# a.test.ts(3,38): error TS2339: Property 'toBeInTheDocument' does not exist on type 'Assertion<void, HTMLElement>'.
With vitest@4.1.11 the same file type-checks.
Problem description:
@testing-library/jest-dom/vitest is the documented way to get the matchers typed under Vitest, and it silently stops working on Vitest 5 — no error at the import site, no runtime failure, just every toBeInTheDocument() failing tsc. Vitest 5.0.0 was released 2026-09-03; the migration guide lists the Assertion<R, T> change under "Assertion Type Parameters".
Suggested solution:
Extend Matchers<R, T>, which is the extension point Vitest 5 documents for custom matchers, instead of Assertion. TestingLibraryMatchers<E, R> already takes the return type as its second parameter, so it slots in directly:
import 'vitest'
import type { ExpectStatic } from 'vitest'
import {type TestingLibraryMatchers} from './matchers'
type AsymmetricMatcher = ReturnType<ExpectStatic['stringContaining']>
declare module 'vitest' {
interface Matchers<R, T>
extends TestingLibraryMatchers<AsymmetricMatcher, R> {}
interface AsymmetricMatchersContaining
extends TestingLibraryMatchers<AsymmetricMatcher, any> {}
}
This is what we ship locally as an ambient jest-dom.d.ts to keep the upgrade green, and it restores all matchers with the correct return type (void for sync assertions, Promise<void> under resolves/rejects).
Caveat: Matchers in Vitest ≤ 4 has a single type parameter, so this declaration is Vitest 5-only; the current Assertion<T> one is ≤ 4-only. If the package wants to keep supporting both, that probably means a version-gated entry point (@testing-library/jest-dom/vitest for ≥ 5 and the old declaration under another name, or the reverse). Happy to open a PR either way if you tell me which shape you prefer.
@testing-library/jest-domversion: 7.0.1nodeversion: 24.19.0jest(orvitest) version: vitest 5.0.0npm(oryarn) version: pnpm 11.21.0typescriptversion: 7.0.2 (same result with 5.9)Relevant code or config:
types/vitest.d.tsas shipped in 7.0.1 (and onmain):Vitest 5.0.0 changed the interface this augments.
Assertionnow takes the return type first and the received type second (vitest/dist/chunks/config.d.*.d.ts):What you did:
Upgraded a Vitest 4.1.11 project (
vitest,@vitest/ui,@vitest/coverage-v8) to 5.0.0, withimport '@testing-library/jest-dom/vitest'in the setup file, and rantsc.What happened:
Every jest-dom matcher disappears from the assertion type. 1,203 errors of the form:
The runtime side is fine —
expect.extendstill registers the matchers and the tests pass. Only the types are gone.Cause: TypeScript only merges interface declarations whose type parameter lists are identical. jest-dom's
Assertion<T = any>(one parameter) no longer matches Vitest'sAssertion<R, T>(two), so the augmentation is dropped. The mismatch itself is reported insidenode_modules(TS2428 "All declarations of 'Assertion' must have identical type parameters"), whichskipLibCheck: truehides — so the only visible symptom is the matchers vanishing.Reproduction:
With
vitest@4.1.11the same file type-checks.Problem description:
@testing-library/jest-dom/vitestis the documented way to get the matchers typed under Vitest, and it silently stops working on Vitest 5 — no error at the import site, no runtime failure, just everytoBeInTheDocument()failingtsc. Vitest 5.0.0 was released 2026-09-03; the migration guide lists theAssertion<R, T>change under "Assertion Type Parameters".Suggested solution:
Extend
Matchers<R, T>, which is the extension point Vitest 5 documents for custom matchers, instead ofAssertion.TestingLibraryMatchers<E, R>already takes the return type as its second parameter, so it slots in directly:This is what we ship locally as an ambient
jest-dom.d.tsto keep the upgrade green, and it restores all matchers with the correct return type (voidfor sync assertions,Promise<void>underresolves/rejects).Caveat:
Matchersin Vitest ≤ 4 has a single type parameter, so this declaration is Vitest 5-only; the currentAssertion<T>one is ≤ 4-only. If the package wants to keep supporting both, that probably means a version-gated entry point (@testing-library/jest-dom/vitestfor ≥ 5 and the old declaration under another name, or the reverse). Happy to open a PR either way if you tell me which shape you prefer.