I'm sort of surprised nobody else has encountered this, but I'm seeing it in two repos with quite different setups.
As of the latest Jest / ts-jest and @types/jest, any test runs throw errors for mock properties not existing on MockedFunction<>. For example:
error TS2339: Property 'mockRejectedValue' does not exist on type 'MockedFunction<RequestAPI<RequestPromise<any>, RequestPromiseOptions, RequiredUriUrl>>'.
29 requestMock.mockRejectedValue(new Error());
The setup itself is very very simple;
import { mocked } from 'ts-jest/utils';
jest.mock('request-promise-native');
import * as request from 'request-promise-native';
const requestMock = mocked(request);
afterEach(() => requestMock.mockRestore());
This looks like it might be similar to https://github.com/kulshekhar/ts-jest/issues/991
mocked() works as in ts-jest 23.x
I'm using ts-jest 23.x. Downgrading @types/jest to 23.3.13 worked for me. Seems like the issue was in @types/jest 23.3.14.
mocked() returns an interface MockWithArgs<T> that extends jest.MockInstance<T>. Recently, jest updated jest.MockInstance to accept 2 type arguments
// @types/jest/index.d.ts line 845
interface MockInstance<T, Y extends any[]> {
To remain compatible, mocked should return an interface that also accepts a second argument. I'll work on a PR for this tonight.
EDIT: Y is the type of the ...args passed to the mocked function.
EDIT 2: Looks like it was changed a month or so ago here.
If you want a quick temporary fix, replace the contents of node_modules/ts-jest/dist/util/testing.d.ts with this:
/// <reference types="jest" />
declare type MockableFunction = (...args: any[]) => any
declare type MethodKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? K : never }[keyof T]
declare type PropertyKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? never : K }[keyof T]
declare type ArgumentsOf<T> = T extends (...args: infer A) => any ? A : never
declare type ConstructorArgumentsOf<T> = T extends new (...args: infer A) => any ? A : never
interface MockWithArgs<T extends MockableFunction> extends jest.MockInstance<ReturnType<T>, ArgumentsOf<T>> {
new (...args: ConstructorArgumentsOf<T>): T
(...args: ArgumentsOf<T>): ReturnType<T>
}
declare type MaybeMockedConstructor<T> = T extends new (...args: any[]) => infer R
? jest.MockInstance<R, ConstructorArgumentsOf<T>>
: {}
declare type MockedFunction<T extends MockableFunction> = MockWithArgs<T> & { [K in keyof T]: T[K] }
declare type MockedFunctionDeep<T extends MockableFunction> = MockWithArgs<T> & MockedObjectDeep<T>
declare type MockedObject<T> = MaybeMockedConstructor<T> &
{ [K in MethodKeysOf<T>]: T[K] extends MockableFunction ? MockedFunction<T[K]> : T[K] } &
{ [K in PropertyKeysOf<T>]: T[K] }
declare type MockedObjectDeep<T> = MaybeMockedConstructor<T> &
{ [K in MethodKeysOf<T>]: T[K] extends MockableFunction ? MockedFunctionDeep<T[K]> : T[K] } &
{ [K in PropertyKeysOf<T>]: MaybeMockedDeep<T[K]> }
export declare type MaybeMockedDeep<T> = T extends MockableFunction
? MockedFunctionDeep<T>
: T extends object
? MockedObjectDeep<T>
: T
export declare type MaybeMocked<T> = T extends MockableFunction ? MockedFunction<T> : T extends object ? MockedObject<T> : T
export declare function mocked<T>(item: T, deep?: false): MaybeMocked<T>
export declare function mocked<T>(item: T, deep: true): MaybeMockedDeep<T>
export declare function mocked<T>(item: T, _deep?: false): MaybeMocked<T> | MaybeMockedDeep<T>;
export {};
EDIT: This won't work for CI builds, to have them pass you'll need to just cast your mock to any like so:
(mockedFn as any).mockImplementation(() => true);
@superhawk610 Thanks, I'll test this out. Any idea when this might get merged?
I'm not sure, I'm relatively new to this project. Hopefully soon! @GeeWee approved the last couple approved PRs, maybe he can better answer that.
Hopefully this can get merged & released soon, as its a pretty big thing IMO.
In the meantime, I worked around this by creating a file to re-export mocked with the new typings:
https://gist.github.com/G-Rath/66246c74ee69d952fde71a1bc3f8687d
This is obviously a hack that forces TypeScript by casting to any, but it compiles & seems compatible with TS (I get autocompletion, type checking, etc).
I'd appreciate some input in trying to get it as hackless as possible - in particular, the deep parameter gave me a lot of grief.
Hey @GeeWee,
Any chance you or one of the other maintainers can review this? It's been over a month, and your current release is broken / unusable.
If the library isn't being maintained any more, that's okay! Happy to fork, I don't expect free work, but a quick yes / no would be wonderful.
Thanks
I'm in the process of merging 994 in.
Unfortunately ts-jest is in a bit of a twilight zone right now, as none of the core maintainers have very much time to dedicate to it. We're doing our best, but response times are probably going to be pretty slow until someone has more free time (or another contributor steps up to the plate)
Thanks for being polite about it.
I've updated to 24.0.1 which appears to have #994 merged in at that point based on the current master but I'm not seeing the expected changes locally. If I manually copy what @superhawk610 pasted into /node_modules/ts-jest/dist/util/testing.d.ts the issues seem to resolve.
Can anyone else confirm if the changes from 994 are indeed in 24.0.1?
Thanks!
Looks like this was merged after the last version was published. I'll publish a new one shortly
@GeeWee Thanks for your help in merging this and thanks @kulshekhar for publishing!
A new version has been published.
Just realised this is still open; closing, as it has been resolved. Sorry for leaving it open!
Most helpful comment
I'm in the process of merging 994 in.
Unfortunately ts-jest is in a bit of a twilight zone right now, as none of the core maintainers have very much time to dedicate to it. We're doing our best, but response times are probably going to be pretty slow until someone has more free time (or another contributor steps up to the plate)
Thanks for being polite about it.