Open arty-name opened 2 years ago
Thanks for reporting this.
I have to say, I see this more as a problem with jest than with jest-dom, if really the solution involves duplicating the code that extends the interface of expect
's return type. I hope there would a better solution where you extend it once, and no matter where you get expect
from, it should work.
After a deeper look, I see that the types of jest-dom extend jest.Matchers
Meanwhile, the types of @jest/globals
simply re-export the type of the expect
package
I’d naively expect that it’s rather expect.Matchers
that should be extended, but after some poking around, I feel that I am out of my depth here.
I'm importing expect
directly from the expect
package, and also struggling to get types working, since the way that jest-dom extends the types is by modifying the jest
module, it seems. But I don't have that, since I'm using expect outside of jest. :(
In my case, I've just switched to expect
that comes from jest
, not from jest/globals
and it works like a charm.
I wasn't able to solve it the proper way either, but I've made a patch on the types coming from @jest/globals
, in a declarations.d.ts
file at the root of my project I've added the following configuration:
import type { TestingLibraryMatchers } from '@types/testing-library__jest-dom/matchers';
// import type { expect } from '@jest/globals'; <-- this was necessary because of my specific setup of cypress + jest, otherwise it was inferring the wrong expect
declare module '@jest/globals/node_modules/expect/build/types' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/ban-types
export interface Matchers<R = void, T = {}>
extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
}
this feels a bit risky because it relies on a path that could change at any moment (@jest/globals/node_modules/expect/build/types
), but it was the best solution I could find for now.
Is there a solution for this yet?
I assumed this should worked but couldn't get it to work yet.
import matchers from '@testing-library/jest-dom/matchers';
import { expect } from '@jest/globals';
expect.extend(matchers);
Looks like Jest@28 should enable that
I added the following to my globals.d.ts
file
import type { TestingLibraryMatchers } from '@types/testing-library__jest-dom/matchers';
declare module '@jest/expect' {
export interface Matchers<R = void, T = {}> extends TestingLibraryMatchers<typeof expect.stringContaining, R> {}
}
@jest/globals
exports from @jest/expect
the expect
function
import type { JestExpect } from '@jest/expect';
export declare const expect: JestExpect;
Just to add: since Jest v28 the above should work equally with declare module 'expect'
or declare module '@jest/expect'
.
By the way, it might be a good idea to include this augmentation declaration in @types/testing-library__jest-dom
. So that matchers would have correct types for those who import { expect } form '@jest/globals'
.
I submitted a PR to DefinitelyTyped that I think should fix this issue: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65981
Wow, thanks @Vinnl I hit this problem yesterday and your fix has got rid of my issue :)
I'm glad that this has fixed the issue for some. Unfortunately, it seems to be a source of problem for others. See https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/65987#discussioncomment-6371630
And we already have a pull request proposing to revert the changes: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65990
I'm not clear what to do here. Would appreciate some help.
@gnapse Hmm, I'm also not sure. I don't know exactly how to reproduce, but looking at the error message, it looks like the problem might be that we're setting T = {}
, whereas in expect
, it's unknown
:
However, if I try to change it in the @testing-library/jest-dom
type definitions for the jest
namespace, I get the same error message - because @types/jest
does define it to be {}
:
I've submitted a followup PR that only changes it for expect
and hope that that fixes it, but I can't verify because I don't know how to reproduce, and I'm not 100% confident about what I'm doing :/
I'm glad that this has fixed the issue for some. Unfortunately, it seems to be a source of problem for others. See DefinitelyTyped/DefinitelyTyped#65987 (comment)
And we already have a pull request proposing to revert the changes: DefinitelyTyped/DefinitelyTyped#65990
I'm not clear what to do here. Would appreciate some help.
@Vinnl @gnapse We face this issue while generating dist folder with script like "build:esm":"tsc" in package.json node_modules/@types/testing-library__jest-dom/index.d.ts:21:15 - error TS2428: All declarations of 'Matchers' must have identical type parameters. node_modules/expect/build/index.d.ts:107:26 - error TS2428: All declarations of 'Matchers' must have identical type parameters.
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65991 Can this reversal PR be temporarily approved to prevent any impact on the systems?
@abhi-works Is your code public somewhere that I could try it out? Or alternatively, could you open node_modules/@types/testing-library__jest-dom/index.d.ts
and apply these changes (i.e. replace the first {}
by unknown
on line 21) manually, and report back whether that fixes the issue for you?
@Vinnl This issue occurs specifically when utilizing the tsc (TypeScript compiler) to generate a compiled distribution bundle. Code is not public,Will try manually in my local
Alternatively, you can replicate the issue by creating a simple React TypeScript component and its corresponding test case that makes use of @testing-library/jest-dom. Afterwards, you can generate the build using tsc to observe the problem @Vinnl
@abhi-works Could you tell Jest and TS version you are using?
If I remember it right, the type arguments if the Matchers
interface differ between versions of Jest. That might be tricky.
@abhi-works Is your code public somewhere that I could try it out? Or alternatively, could you open
node_modules/@types/testing-library__jest-dom/index.d.ts
and apply these changes (i.e. replace the first{}
byunknown
on line 21) manually, and report back whether that fixes the issue for you?@Vinnl This issue occurs specifically when utilizing the tsc (TypeScript compiler) to generate a compiled distribution bundle. Code is not public,Will try manually in my local
@Vinnl @gnapse https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65991/files Works locally
I added the following to my
globals.d.ts
fileimport type { TestingLibraryMatchers } from '@types/testing-library__jest-dom/matchers'; declare module '@jest/expect' { export interface Matchers<R = void, T = {}> extends TestingLibraryMatchers<typeof expect.stringContaining, R> {} }
@jest/globals
exports from@jest/expect
theexpect
functionimport type { JestExpect } from '@jest/expect'; export declare const expect: JestExpect;
we'd better to install @jest/expect
explicitly
For me I had to install @jest/expect
alongside with @jest/globals
in order to make import "@testing-library/jest-dom/jest-globals";
to correctly extend the expect type.
@testing-library/jest-dom
version: 5.16.1node
version: v16.13.1yarn
version: 1.22.17Relevant code or config:
What you did:
I imported jest globals from '@jest/globals'
What happened:
I got the TypeScript error message:
TS2339: Property 'toHaveAttribute' does not exist on type 'Matchers '.
Reproduction:
Problem description:
The custom matchers provided by jest-dom cannot be used in TypeScript if the
expect
is imported from@jest/globals
. Only the globalexpect
is modified, apparently.Suggested solution:
Extend the interface of
expect
in the@jest/globals
as well.