Skip to content
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

Vitest typings are broken in 6.5.0 #629

Open
billyjanitsch opened this issue Aug 27, 2024 · 1 comment
Open

Vitest typings are broken in 6.5.0 #629

billyjanitsch opened this issue Aug 27, 2024 · 1 comment

Comments

@billyjanitsch
Copy link

billyjanitsch commented Aug 27, 2024

  • @testing-library/jest-dom version: 6.5.0
  • node version: 20.15.1
  • jest (or vitest) version: Vitest 2.0.5
  • npm (or yarn) version: npm 10.8.2

Relevant code or config:

See reproduction repo below.

What you did:

Followed the setup instructions for Vitest in the readme.

What happened:

Running the TS checker in a minimal environment produces the following errors:

node_modules/@testing-library/jest-dom/types/vitest.d.ts:7:32 - error TS2339: Property 'stringContaining' does not exist on type 'ExpectStatic'.

7       ReturnType<typeof expect.stringContaining>,
                                 ~~~~~~~~~~~~~~~~

node_modules/@testing-library/jest-dom/types/vitest.d.ts:10:13 - error TS2310: Type 'AsymmetricMatchersContaining' recursively references itself as a base type.

10   interface AsymmetricMatchersContaining
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

node_modules/@testing-library/jest-dom/types/vitest.d.ts:12:32 - error TS2339: Property 'stringContaining' does not exist on type 'ExpectStatic'.

12       ReturnType<typeof expect.stringContaining>,
                                  ~~~~~~~~~~~~~~~~

Reproduction:

I've isolated the problem to a barebones setup:

https://github.com/billyjanitsch/vitest-jest-dom-types

Problem description:

#612 (which was released in 6.5.0) updated the typings for Vitest in a way that seems to be incompatible with Vitest's own definitions. I understand that that PR was an attempt to align the typings with the official recommendations, but it seems to be broken.

Suggested solution:

I'd suggest reverting #612 until it can be tested and fixed.

For a long-term fix, this is just a guess based on the TS error and looking at the type defs, but I think the problem might be related to importing type expect from vitest and then using that type when extending the vitest module type. This recursive self-reference might not be allowed/supported by the TS compiler.

cc @vorant94

@vorant94
Copy link
Contributor

vorant94 commented Sep 3, 2024

thanks for noticing it

as for long term solution I'm still in progress of investigation, but it seems the problem is in AsymmetricMatchersContaining referencing ReturnType<typeof expect.stringContaining>, not in the way how we import stuff from `vitest

here what I see in @vitest/expect/dist/index.d.ts:

interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {
    <T>(actual: T, message?: string): Assertion<T>;
    extend: (expects: MatchersObject) => void;
    anything: () => any;
    any: (constructor: unknown) => any;
    getState: () => MatcherState;
    setState: (state: Partial<MatcherState>) => void;
    not: AsymmetricMatchersContaining;
}
interface AsymmetricMatchersContaining {
    stringContaining: (expected: string) => any;
    objectContaining: <T = any>(expected: T) => any;
    arrayContaining: <T = unknown>(expected: Array<T>) => any;
    stringMatching: (expected: string | RegExp) => any;
    closeTo: (expected: number, precision?: number) => any;
}

Here i see that ExpectStatic (the underlying type of expect mentioned above) extending AsymmetricMatchersContaining and after my changes AsymmetricMatchersContaining started at the same time to reference typeof expect.stringContaining i.e. ExpectStatic. So the TS doesn't know what type is source one and what is derived one, essentially creating this circular reference issue

we can validate it by just removing AsymmetricMatchersContaining from file I previously changed and see npm run test works fine (tested on repo you provided, thanks for that).

import {type expect} from 'vitest'
import {type TestingLibraryMatchers} from './matchers'

declare module 'vitest' {
  interface Assertion<T = any>
      extends TestingLibraryMatchers<
          ReturnType<typeof expect.stringContaining>,
          T
      > {}
}

I didn't have much spare time recently, hence replied here only a week after issue is opened, but i'll try to dive deeper on vitest AsymmetricMatchersContaining, why is it recommended to extend both Assertion and AsymmetricMatchersContaining and so on. as well as into what is the purpose of those generics from the side of @testing-library/jest-dom.

I'll update on my findings here alongside (hopefully) with a PR with long-term solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants