-
-
Notifications
You must be signed in to change notification settings - Fork 223
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
Current setup instructions for Vitest don't work for asymmetric matchers' typings #649
Comments
I added these instructions in #610, but I'm not a Vitest user and wasn't sure they were complete, so thank you for chiming in about where they need more work. Thank you also for the reproduction examples! It really helps someone like me that's kinda stumbling my way through Vitest stuff. I will take a look this weekend and see what I can come up with. |
Related issue I've just submitted: #652 I think the issue is that the |
PR to allow declaration merging: #653 |
@acidoxee I was able to get this working without the above PR. Here is your updated reproduction. https://stackblitz.com/edit/vitest-dev-vitest-whsqfe?file=jest-extended.d.ts Here's the import "jest-extended";
import "vitest";
declare module "vitest" {
interface Assertion<T = any> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining<T = any> extends CustomMatchers<T> {}
interface ExpectStatic extends CustomMatchers {}
} |
@keeganwitt Here's vitest's docs if they are useful, though I get errors following those steps. |
Co-authored-by: Christopher Dierkens <cjdierkens@gmail.com>
That's a good start @cdierkens, thanks! Although I can't seem to make this work as soon as I add my own custom matchers (following the docs you've linked, which is exactly what I had followed on my own). This was kinda always the problem: the setup for my own matchers (exclusively) works perfectly, and so does the setup you're suggesting with only |
Would it work to define an interface for your custom matchers and extend that interface in addition to jest-extended's? Shooting a bit from the hip here, since I don't have a test project with this setup. |
@keeganwitt That worked for me! Here's the updated stackblitz that shows it working: https://stackblitz.com/edit/vitest-dev-vitest-whsqfe?file=test%2Fextended.test.ts import 'jest-extended';
import 'vitest';
interface MyCustomMatchers {
toBeFoo(): any;
}
declare module 'vitest' {
interface Assertion<T = any> extends CustomMatchers<T>, MyCustomMatchers {}
interface AsymmetricMatchersContaining<T = any>
extends CustomMatchers<T>,
MyCustomMatchers {}
interface ExpectStatic extends CustomMatchers, MyCustomMatchers {}
} |
Co-authored-by: Christopher Dierkens <cjdierkens@gmail.com>
OK yeah this time it seems to work nicely, well done @keeganwitt @cdierkens 👏 thanks a bunch for the help! |
Using Also here's my workaround to use the old // inspired by https://jest-extended.jestcommunity.dev/docs/getting-started/setup#vitest-typescript-types-setup
import type jestExtended from "jest-extended";
import "vitest";
interface MyCustomMatchers<R> extends Record<string, unknown> {
toHaveBeenCalledOnceWith: (typeof jestExtended<R>)["toHaveBeenCalledExactlyOnceWith"];
}
declare module "vitest" {
interface Assertion<T = unknown> extends CustomMatchers<T>, MyCustomMatchers<T> {}
interface AsymmetricMatchersContaining<T = unknown> extends CustomMatchers<T>, MyCustomMatchers<T> {}
interface ExpectStatic extends CustomMatchers, MyCustomMatchers {}
} Actually, looks like it doesn't work in all cases, unfortunately. Will patch it up instead for now... |
I am currently migrating away from Jest to Vitest. I used to have Jest tests that use jest-extended, hence I tried keeping jest-extended as well in the migrated tests with Vitest. I followed official instructions in the docs to setup jest-extended for Vitest. My tests are now fully implemented with Vitest and leverage jest-extended matchers as well. I've already went through previous issues/PRs regarding Vitest and its TS setup.
package
version: 4.0.1node
version: 16.20.0 on reproduction repository (same problem on my prod, which is 18.17.1)npm
(oryarn
) version: npm 9.4.2 on reproduction repository (same problem on my prod, which is yarn 1.22.19)What happened: Runtime works flawlessly and all tests pass, as well as typings for "classic" matchers ✅ But typings of asymmetric matchers don't seem to work ❌ If I follow the official instructions from the docs, I don't have any completion for jest-extended's matchers when used in an asymmetric manner. For instance, TS says
Property 'toBeNumber' does not exist on type 'ExpectStatic'.(2339)
.Reproduction repository: https://stackblitz.com/edit/vitest-dev-vitest-rsfqnf?file=test%2Fextended.test.ts
Possible solution: I've tried a few things, with OK-ish results, but never perfect, and I'm unfortunately not familiar enough with the way TS module types work to be sure to provide an adequate solution that wouldn't break for other users.
Try 1
The first thing I tried was append the other part of the setup instructions in the
jest-extended.d.ts
file, for which the docs mention this is only for Vitest < 0.31.0. I understand that Vitest went from using aVi
namespace to avitest
module declaration (which is probably why the docs mention the version thing), so I've just added theinterface AsymmetricMatchersContaining .....
declaration in the existing module declaration locally:declare module 'vitest' { interface Assertion<T = any> extends CustomMatchers<T> {} + interface AsymmetricMatchersContaining extends CustomMatchers<any> {} }
This seems to work at first, and is closer to what Vitest itself suggests to write when extending matchers, since there are no more TS problems, but it just seems like so because jest-extended's matchers now appear to be typed
any
. There's also not any completion for those matchers, as you can see if you try typing one from scratch.Reproduction: https://stackblitz.com/edit/vitest-dev-vitest-cwyxfl?file=test%2Fextended.test.ts
Try 2
I can't remember why I tried this, but I've then replaced the
AsymmetricMatchersContaining
extension like so:This now provides proper completion and types for jest-extended's asymmetric matchers, but now those asymmetric matchers' return types do not match with the expected object properties' types. For instance, notice how
expect.toBeNumber()
returnsvoid
, while the expected type is obviouslynumber
. If I replaceexpect.toBeNumber()
byexpect.any(Number)
, this now works perfectly.Reproduction: https://stackblitz.com/edit/vitest-dev-vitest-ymmvae?file=test%2Fextended.test.ts
Finding the proper solution
I'm not sure what the correct solution would be. My hunch of using
extends Assertion
left me stunned and unsure as to why this "works", but then all typing assertions nicely provided by Vitest are breaking due to mismatches between the expected properties and what jest-extended's matchers apparently return. Maybe that's just because jest-extended's matchers were not meant to be used this way (type-wise)? I'd also like to find a setup that works if I also have to add other custom matchers than jest-extended's, which is actually my case (I simplified here for the sake of simplicity), the setup should make sure that jest-extended's matchers typings work but don't override those of other custom matchers. If you could help me figure out what (or if anything) is wrong and how we could make all of this work, I'd greatly appreciate it 🙏The text was updated successfully, but these errors were encountered: