vitest: Property 'mockClear' does not exist on type 'Mocked<...>'.
Describe the bug
I’m trying to use the Mocked
utility type from the vitest
package, but when I try to invoke .mockClear()
on the result, TypeScript claims that the property does not exist. In contrast, the Mock
utility type does not have the same issue.
Reproduction
import { Mocked, Mock, vi } from "vitest";
const m1: Mock<[], void> = vi.fn(fn);
m1.mockClear(); // no issue
const m2: Mocked<typeof fn> = vi.fn(fn);
m2.mockClear(); // Property 'mockClear' does not exist on type 'Mocked<() => void>'.
function fn() {}
System Info
System:
OS: macOS 14.1.2
CPU: (10) arm64 Apple M1 Pro
Memory: 156.53 MB / 32.00 GB
Shell: 5.9 - /opt/homebrew/bin/zsh
Binaries:
Node: 21.4.0 - /opt/homebrew/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 10.2.4 - /opt/homebrew/bin/npm
pnpm: 8.10.3 - /opt/homebrew/bin/pnpm
Browsers:
Chrome: 120.0.6099.71
Edge: 120.0.2210.61
Safari: 17.1.2
npmPackages:
@vitejs/plugin-react: ^4.2.1 => 4.2.1
vitest: ^1.0.4 => 1.0.4
Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn’t already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
About this issue
- Original URL
- State: open
- Created 7 months ago
- Comments: 18 (10 by maintainers)
By the way, notice that all the changes I was making had extensive type tests. Type inference is powerful, but keep in mind that TypeScript is constantly improving it. This means that not all users might be able to use the typings. The lowest supported TypeScript version must be set. And here is the problem: how to test that?
The short answer:
tstyche --target 4.8,5.0,latest
.With all the changes I made in Jest repo, I have contributed ca. 1000 type test assertions. As usually: solving a problem brings you to another problem. In this case, type testing at scale was rather an issue. I was hitting lots of limitations, one of them was running tests on specified TypeScript version. To address all that, I have build TSTyche, a type testing tool for TypeScript. Documentation is here: https://tstyche.org
Of course, I did consider other type testing libraries around.
expect-type
was one of them. Itsexpect
style API is great andexpect-type
is a nice tool for small projects. But it does not scale.I was already mentioning TSTyche in other issues. Now you can see it from another perspective.
Interesting. I did not realize they were different, we will need to align them then.
FWIW the typings shipped with
@types/jest
and imported from@jest/globals
are different things. The migration guide demonstrates migration from@types/jest
only.The mock related typings from
@jest/globals
take only one argument (type of the function) and infer all what is needed. Here are the usage details of the Jest built-in types: https://jestjs.io/docs/mock-function-api#typescript-usage@ezzatron is pointing not to
@types/jest
, but to@jest/globals
. And it seems like the suggestion is to consider reshaping the mock types in similar fashion.Thanks for explaining the motivation and comparison with
jest.Mock
. I think overall this issue could be considered as a feature request than jest-compatibility bug?I tested a few cases below and it looks like there are some cases typescript can still magically infer
vi.fn<TArgs, TReturn>
. Could these be convenient enough? (These usages are not documented, so probably it’s not guaranteed to work forever though…)Also in my opinion, if you’re mocking, then it’s likely that you want to lie about type-safety at some point, so I feel there’s nothing wrong with using something like
vi.fn() as any
as a quick escape-hatch.It’s using mapped type, so I think it’s only testing each property
T[P]
is function instead ofT
itself.Can you explain your higher level goal with the use of Vitest’s typing utility? For example, why
Mock
type is not enough (not convenient) for your use case.It’s hard to suggest without more contexts, but perhaps
MockedFunction
could be what you’re looking for?https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgWQgYwNYFMAmAaFdDA1TXAMQFcA7NGYCaggN2DgF84AzKCEOAESsYWAM4wBAbgBQ0tI3FwQARgBchTAB4A2gF0WEYDgB8cALxxWAOi7UAFLYCUMlVZBEAwgBssAQyh2znAA9MFw1BBwwKKilFiy8tSKIABM6qTYOJowAJ5gWBBc3NSmFta2DtTO0qFKKW6ePv6BkiFhAAq8+bA5cADk7pjeflB9cDgQYuEQ8FgAHtHwjHC5+f0ZuJqB5qbMhiZ9VgkK8CAAzOlEFDR0DNTZeQVFtqWWwDb2Ti5nDUNNAdVpFwbvRlhVHIgOEA