diff --git a/types/jest-when/index.d.ts b/types/jest-when/index.d.ts index 386911ed7c53cc..9a9fb9a55f8b5d 100644 --- a/types/jest-when/index.d.ts +++ b/types/jest-when/index.d.ts @@ -11,10 +11,10 @@ export interface WhenMock extends jest.Mock; mockReturnValue(value: T): WhenMock; mockReturnValueOnce(value: T): WhenMock; - mockResolvedValue(value: T | PromiseLike): WhenMock, Y>; - mockResolvedValueOnce(value: T | PromiseLike): WhenMock, Y>; - mockRejectedValue(value: T | PromiseLike): WhenMock, Y>; - mockRejectedValueOnce(value: T | PromiseLike): WhenMock, Y>; + mockResolvedValue(value: jest.ResolvedValue): WhenMock; + mockResolvedValueOnce(value: jest.ResolvedValue): WhenMock; + mockRejectedValue(value: jest.RejectedValue): WhenMock; + mockRejectedValueOnce(value: jest.RejectedValue): WhenMock; } export type When = (fn: jest.Mock) => WhenMock; diff --git a/types/jest/index.d.ts b/types/jest/index.d.ts index 0cc1999096aec3..d66e509c834ca3 100644 --- a/types/jest/index.d.ts +++ b/types/jest/index.d.ts @@ -36,8 +36,6 @@ declare var xtest: jest.It; declare const expect: jest.Expect; -type ArgsType = T extends (...args: infer A) => any ? A : never; - interface NodeRequire { /** * Returns the actual module instead of a mock, bypassing all checks on @@ -237,6 +235,9 @@ declare namespace jest { } type EmptyFunction = () => void; + type ArgsType = T extends (...args: infer A) => any ? A : never; + type RejectedValue = T extends PromiseLike ? any : never; + type ResolvedValue = T extends PromiseLike ? U | T : never; // see https://github.com/Microsoft/TypeScript/issues/25215 type NonFunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? never : K }[keyof T] & string; type FunctionPropertyNames = { [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never }[keyof T] & string; @@ -807,7 +808,7 @@ declare namespace jest { * myApi.myApiMethod.mockImplementation(() => "test"); */ type Mocked = { - [P in keyof T]: T[P] & MockInstance>; + [P in keyof T]: T[P] extends (...args: any[]) => any ? MockInstance, ArgsType>: T[P]; } & T; interface MockInstance { @@ -915,7 +916,7 @@ declare namespace jest { /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.resolve(value));` */ - mockResolvedValue(value: T | PromiseLike): Mock, Y>; + mockResolvedValue(value: ResolvedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.resolve(value));` * @@ -935,7 +936,7 @@ declare namespace jest { * }); * */ - mockResolvedValueOnce(value: T | PromiseLike): Mock, Y>; + mockResolvedValueOnce(value: ResolvedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.reject(value));` * @@ -947,7 +948,7 @@ declare namespace jest { * await asyncMock(); // throws "Async error" * }); */ - mockRejectedValue(value: any): Mock, Y>; + mockRejectedValue(value: RejectedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.reject(value));` @@ -965,7 +966,7 @@ declare namespace jest { * }); * */ - mockRejectedValueOnce(value: any): Mock, Y>; + mockRejectedValueOnce(value: RejectedValue): Mock; } /** diff --git a/types/jest/jest-tests.ts b/types/jest/jest-tests.ts index eee5d73922b960..15702d45a4a4c5 100644 --- a/types/jest/jest-tests.ts +++ b/types/jest/jest-tests.ts @@ -423,6 +423,61 @@ const spy6 = jest.spyOn(spiedTarget2, "value", "set"); // should compile jest.fn().mockImplementation((test: number) => test); +jest.fn().mockResolvedValue(1); + +interface Type1 { a: number; } +interface Type2 { b: number; } +class TestMocked { + field: string; + test1(x: Type1): Promise { + return Promise.resolve(x); + } + test2(x: Promise): Promise { + return x; + } + test3(x: Promise): Promise { + return x.then(() => ({ b: 1 })); + } + test4(x: Type1): Type1 { + return x; + } +} + +const mocked: jest.Mocked = new TestMocked() as any; +mocked.test1.mockImplementation(() => Promise.resolve({ a: 1 })); +mocked.test1.mockReturnValue(Promise.resolve({ a: 1 })); +// $ExpectType Mock, [Type1]> +mocked.test1.mockResolvedValue({ a: 1 }); +mocked.test1.mockResolvedValueOnce({ a: 1 }); +// $ExpectType Mock, [Type1]> +mocked.test1.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test1.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType Mock, [Promise]> +mocked.test2.mockResolvedValue({ a: 1 }); +mocked.test2.mockResolvedValueOnce({ a: 1 }); +// $ExpectType Mock, [Promise]> +mocked.test2.mockResolvedValue(Promise.resolve({ a: 1 })); +mocked.test2.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectType Mock, [Promise]> +mocked.test3.mockResolvedValue({ b: 1 }); +mocked.test3.mockResolvedValueOnce({ b: 1 }); +// $ExpectType Mock, [Promise]> +mocked.test3.mockResolvedValue(Promise.resolve({ b: 1 })); +mocked.test3.mockResolvedValueOnce(Promise.resolve({ b: 1 })); +mocked.test3.mockRejectedValue(new Error()); +mocked.test3.mockRejectedValueOnce(new Error()); +// $ExpectError +mocked.test4.mockResolvedValue({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValueOnce({ a: 1 }); +// $ExpectError +mocked.test4.mockResolvedValue(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockResolvedValueOnce(Promise.resolve({ a: 1 })); +// $ExpectError +mocked.test4.mockRejectedValue(new Error()); +// $ExpectError +mocked.test4.mockRejectedValueOnce(new Error()); /* Snapshot serialization */