Skip to content

Commit

Permalink
🤖 Merge PR DefinitelyTyped#57776 [jest] adding definitions for `mocke…
Browse files Browse the repository at this point in the history
…d` function by @k-rajat19

* mocked

* fixing jest-tests

* prettier

* removing prettier changes

* tslint

* making requested changes

* jest-tests

* removing comments
  • Loading branch information
k-rajat19 authored and Martin Badin committed Feb 23, 2022
1 parent 72763e5 commit 9418133
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
49 changes: 48 additions & 1 deletion types/jest/index.d.ts
@@ -1,4 +1,4 @@
// Type definitions for Jest 27.0
// Type definitions for Jest 27.4
// Project: https://jestjs.io/
// Definitions by: Asana (https://asana.com)
// Ivo Stratev <https://github.com/NoHomey>
Expand Down Expand Up @@ -178,6 +178,25 @@ declare namespace jest {
* Mocks a module with an auto-mocked version when it is being required.
*/
function mock(moduleName: string, factory?: () => unknown, options?: MockOptions): typeof jest;

/**
* The mocked test helper provides typings on your mocked modules and even
* their deep methods, based on the typing of its source. It makes use of
* the latest TypeScript feature, so you even have argument types
* completion in the IDE (as opposed to jest.MockInstance).
*
* Note: while it needs to be a function so that input type is changed, the helper itself does nothing else than returning the given input value.
*/
function mocked<T>(item: T, deep?: false): MaybeMocked<T>;
/**
* The mocked test helper provides typings on your mocked modules and even
* their deep methods, based on the typing of its source. It makes use of
* the latest TypeScript feature, so you even have argument types
* completion in the IDE (as opposed to jest.MockInstance).
*
* Note: while it needs to be a function so that input type is changed, the helper itself does nothing else than returning the given input value.
*/
function mocked<T>(item: T, deep: true): MaybeMockedDeep<T>;
/**
* Returns the actual module instead of a mock, bypassing all checks on
* whether the module should receive a mock implementation or not.
Expand Down Expand Up @@ -312,6 +331,34 @@ declare namespace jest {
virtual?: boolean | undefined;
}

type MockableFunction = (...args: any[]) => any;
type MethodKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? K : never }[keyof T];
type PropertyKeysOf<T> = { [K in keyof T]: T[K] extends MockableFunction ? never : K }[keyof T];
type ArgumentsOf<T> = T extends (...args: infer A) => any ? A : never;
type ConstructorArgumentsOf<T> = T extends new (...args: infer A) => any ? A : never;

interface MockWithArgs<T extends MockableFunction> extends MockInstance<ReturnType<T>, ArgumentsOf<T>> {
new (...args: ConstructorArgumentsOf<T>): T;
(...args: ArgumentsOf<T>): ReturnType<T>;
}
type MaybeMockedConstructor<T> = T extends new (...args: any[]) => infer R
? MockInstance<R, ConstructorArgumentsOf<T>>
: T;
type MockedFn<T extends MockableFunction> = MockWithArgs<T> & { [K in keyof T]: T[K] };
type MockedFunctionDeep<T extends MockableFunction> = MockWithArgs<T> & MockedObjectDeep<T>;
type MockedObject<T> = MaybeMockedConstructor<T> & {
[K in MethodKeysOf<T>]: T[K] extends MockableFunction ? MockedFn<T[K]> : T[K];
} & { [K in PropertyKeysOf<T>]: T[K] };
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]> };
type MaybeMockedDeep<T> = T extends MockableFunction
? MockedFunctionDeep<T>
: T extends object // eslint-disable-line @typescript-eslint/ban-types
? MockedObjectDeep<T>
: T;
// eslint-disable-next-line @typescript-eslint/ban-types
type MaybeMocked<T> = T extends MockableFunction ? MockedFn<T> : T extends object ? MockedObject<T> : T;
type EmptyFunction = () => void;
type ArgsType<T> = T extends (...args: infer A) => any ? A : never;
type ConstructorArgsType<T> = T extends new (...args: infer A) => any ? A : never;
Expand Down
5 changes: 5 additions & 0 deletions types/jest/jest-tests.ts
Expand Up @@ -531,6 +531,11 @@ class SpyableClass {
// $ExpectType SpyInstance<SpyableClass, [number, string]> || SpyInstance<SpyableClass, [a: number, b: string]>
jest.spyOn({ SpyableClass }, "SpyableClass");

// $ExpectType MockedObject<{}>
jest.mocked({});
// $ExpectError
jest.mocked();

interface Type1 {
a: number;
}
Expand Down

0 comments on commit 9418133

Please sign in to comment.