From 3fbd136e7f59361b608151663e5596e4d84450b0 Mon Sep 17 00:00:00 2001 From: antoinebrault Date: Tue, 5 Feb 2019 21:17:57 -0500 Subject: [PATCH 1/3] [jest] fix type inference for Mocked & mockResolvedValue/mockRejectedValue --- types/jest/index.d.ts | 10 ++++---- types/jest/jest-tests.ts | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/types/jest/index.d.ts b/types/jest/index.d.ts index cfc9be20709cc9..6cee72a6d174a9 100644 --- a/types/jest/index.d.ts +++ b/types/jest/index.d.ts @@ -804,7 +804,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 { @@ -912,7 +912,7 @@ declare namespace jest { /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.resolve(value));` */ - mockResolvedValue(value: T | PromiseLike): Mock, Y>; + mockResolvedValue(value: T extends PromiseLike ? U | T : never): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.resolve(value));` * @@ -932,7 +932,7 @@ declare namespace jest { * }); * */ - mockResolvedValueOnce(value: T | PromiseLike): Mock, Y>; + mockResolvedValueOnce(value: T extends PromiseLike ? U | T : never): Mock; /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.reject(value));` * @@ -944,7 +944,7 @@ declare namespace jest { * await asyncMock(); // throws "Async error" * }); */ - mockRejectedValue(value: any): Mock, Y>; + mockRejectedValue(value: T extends PromiseLike ? any : never): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.reject(value));` @@ -962,7 +962,7 @@ declare namespace jest { * }); * */ - mockRejectedValueOnce(value: any): Mock, Y>; + mockRejectedValueOnce(value: T extends PromiseLike ? any : never): Mock; } /** diff --git a/types/jest/jest-tests.ts b/types/jest/jest-tests.ts index c2e930c26f29cf..00ccd381067535 100644 --- a/types/jest/jest-tests.ts +++ b/types/jest/jest-tests.ts @@ -412,6 +412,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 */ From 1f5d6d6cc4f6ff4446fcd18b7fd55cce627a4b22 Mon Sep 17 00:00:00 2001 From: antoinebrault Date: Tue, 5 Feb 2019 21:47:22 -0500 Subject: [PATCH 2/3] fix jest-when --- types/jest-when/index.d.ts | 8 ++++---- types/jest/index.d.ts | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/types/jest-when/index.d.ts b/types/jest-when/index.d.ts index 386911ed7c53cc..1d1c83b206d1ac 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: ResolvedValue): WhenMock; + mockResolvedValueOnce(value: ResolvedValue): WhenMock; + mockRejectedValue(value: RejectedValue): WhenMock; + mockRejectedValueOnce(value: RejectedValue): WhenMock; } export type When = (fn: jest.Mock) => WhenMock; diff --git a/types/jest/index.d.ts b/types/jest/index.d.ts index 6cee72a6d174a9..f342f27580db79 100644 --- a/types/jest/index.d.ts +++ b/types/jest/index.d.ts @@ -37,6 +37,8 @@ declare var xtest: jest.It; declare const expect: jest.Expect; 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; interface NodeRequire { /** @@ -912,7 +914,7 @@ declare namespace jest { /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.resolve(value));` */ - mockResolvedValue(value: T extends PromiseLike ? U | T : never): Mock; + mockResolvedValue(value: ResolvedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.resolve(value));` * @@ -932,7 +934,7 @@ declare namespace jest { * }); * */ - mockResolvedValueOnce(value: T extends PromiseLike ? U | T : never): Mock; + mockResolvedValueOnce(value: ResolvedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementation(() => Promise.reject(value));` * @@ -944,7 +946,7 @@ declare namespace jest { * await asyncMock(); // throws "Async error" * }); */ - mockRejectedValue(value: T extends PromiseLike ? any : never): Mock; + mockRejectedValue(value: RejectedValue): Mock; /** * Simple sugar function for: `jest.fn().mockImplementationOnce(() => Promise.reject(value));` @@ -962,7 +964,7 @@ declare namespace jest { * }); * */ - mockRejectedValueOnce(value: T extends PromiseLike ? any : never): Mock; + mockRejectedValueOnce(value: RejectedValue): Mock; } /** From d4ac3a53a7ea2e8e4e975c4ea0e3e052d5a34b41 Mon Sep 17 00:00:00 2001 From: antoinebrault Date: Fri, 8 Feb 2019 22:27:03 -0500 Subject: [PATCH 3/3] move custom types to jest namespace --- types/jest-when/index.d.ts | 8 ++++---- types/jest/index.d.ts | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/types/jest-when/index.d.ts b/types/jest-when/index.d.ts index 1d1c83b206d1ac..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: ResolvedValue): WhenMock; - mockResolvedValueOnce(value: ResolvedValue): WhenMock; - mockRejectedValue(value: RejectedValue): WhenMock; - mockRejectedValueOnce(value: RejectedValue): WhenMock; + 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 f342f27580db79..840d9b7fa0aadb 100644 --- a/types/jest/index.d.ts +++ b/types/jest/index.d.ts @@ -36,10 +36,6 @@ declare var xtest: jest.It; declare const expect: jest.Expect; -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; - interface NodeRequire { /** * Returns the actual module instead of a mock, bypassing all checks on @@ -239,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; interface DoneCallback { (...args: any[]): any;