-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug]: Using @jest/globals expect breaks extensions #12267
Comments
Here's the best workaround I've found so far. I've created a type declaration file, which combines the return types of // File: types/jest-matcher-fix/index.d.ts
/// <reference types="jest" />
// This line is needed to pull in jest-extended. Remove if you're not using jest-extended,
// or if you're including its types another way.
/// <reference path="../../node_modules/jest-extended/types/index.d.ts" />
/**
* Overrides the `@jest/globals` module so that `expect` returns a `Matcher<T>`
* type that is compatible with matcher extensions.
*
* Without this, `@jest/globals expect()` returns a new type, which is not type-compatible with
* `jest.Matchers<R>`, which all the extending libraries expect.
*/
declare module '@jest/globals' {
// IMPORTANT: These imports have to be within the declared module,
// otherwise the module patch doesn't work outside of this file.
import type { Jest } from '@jest/environment';
import type { Global } from '@jest/types';
import type importedExpect from 'expect';
export type CombinedMatchers<T> = jest.JestMatchers<T> & importedExpect.Matchers<void, T>;
interface ExpectReturningCombinedMatchers {
<T = unknown>(actual: T): CombinedMatchers<T>;
}
export type CombinedExpect = jest.Expect & typeof importedExpect & ExpectReturningCombinedMatchers;
// I couldn't figure out a way to avoid duplicating all the globals/types in
// ../../node_modules/@jest/globals/build/index.d.ts, so here they are again.
//
// The only change from `@jest/globals` is `expect: CombinedExpect`.
export const jest: Jest;
export const expect: CombinedExpect;
export const it: Global.GlobalAdditions['it'];
export const test: Global.GlobalAdditions['test'];
export const fit: Global.GlobalAdditions['fit'];
export const xit: Global.GlobalAdditions['xit'];
export const xtest: Global.GlobalAdditions['xtest'];
export const describe: Global.GlobalAdditions['describe'];
export const xdescribe: Global.GlobalAdditions['xdescribe'];
export const fdescribe: Global.GlobalAdditions['fdescribe'];
export const beforeAll: Global.GlobalAdditions['beforeAll'];
export const beforeEach: Global.GlobalAdditions['beforeEach'];
export const afterEach: Global.GlobalAdditions['afterEach'];
export const afterAll: Global.GlobalAdditions['afterAll'];
} When this type declaration is included in the tsconfig via: ...
"typeRoots": [
"./node_modules/@types",
"./types"
],
"types": [
"jest",
"tslib",
"node",
"jest-matcher-fix"
]
... using |
@johncrim Looking at your reproduction repo it seems like you were experimenting to find the best solution. I was just wondering to ask if you did try the latest alpha release too? After #12344, it should be trivial to extend I just though you might be interested to give it a try. It would be nice to hear if all works as expected in real world. Or perhaps any further improvement is necessary? |
@mrazauskas - Thank you for the update. I did not see that there was a fix for this in the alpha until your comment, but I will try it out and follow up. This example certainly looks great: One thing that I'll have to look out for is whether each of the libraries will need to |
The plan is to make |
Let's track in #12424 |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Version
27.4.7
Steps to reproduce
There are two versions of the same test, one using
the other using the ambient/global expect.
The test using
import { expect } from '@jest/globals';
fails with:because the type returned from
expect()
in '@jest/globals' (Matchers<void, T>
inexpect
module) does not match the type returned fromexpect()
in@types/jest
(jest.JestMatchers<T>
).Expected behavior
expect
extension typing continues to work whether you're importing from@jest/globals
or not.Actual behavior
expect
extensions fail to compile when importingexpect
from@jest/globals
. If you can get around the typing issue (via casting orany
or creating a global type def file to fix the issue) the runtime behavior works as expected.Additional context
This breaks all expect extensions in libraries I'm aware of, including:
It also breaks anyone using private
expect
extensions using the approach that is widely documented and used - a file like:will no longer enable compilation given
expect(x).equalsFoo('message');
.The obvious workaround is "don't use @jest/globals", but that is not viable in many codebases - particularly if using ES Modules. In our codebase, we have jasmine types and jest types, and using
@jest/globals
is necessary now that we've changed to ES Modules.I believe this is the same issue as #10642. #10642 was correctly reported, but it was incorrectly closed. This comment about creating a type def file for expect extensions is helpful, but is not a fix for #10642. Hopefully this issue provides more clarity.
Environment
The text was updated successfully, but these errors were encountered: