I’m writing a utility type for jest, it looks like this:
export type MockedService<T extends object> = {
[K in keyof T]: jest.MaybeMockedDeep<T[K]>;
};
The purpose is take the interface for our services, and return a type equivilent to wrapping jest.mocked<TheFunctionType>
around each of them.
This works well, with one wrinkle:
interface Foo {
getA: (a: string, b: string) => Promise<{ c: string }>;
getB: (e: number, f: number) => Promise<{ g: string }>;
}
const correctUsageWithDefaultsWithMockedUtil: MockedService<Foo> = {
// use of jest.mocked means that the mock implementations are typed properly
// @ts-expect-error - incorrect return value
getA: jest.mocked<Foo['getA']>(jest.fn()).mockResolvedValue('abc'),
// correct return value
getB: jest.mocked<Foo['getB']>(jest.fn()).mockResolvedValue({ g: 'abc' })
};
const correctUsageWithDefaults: MockedService<Foo> = {
getA: jest.fn().mockRejectedValue(new Error('not implemented')),
// nb. The mock return values are not stricted enforced, if you
// don't wrap with jest.mocked!
getB: jest.fn().mockReturnValue('abc')
};
If we don’t wrap our jest.fn()
with a jest.mocked<TheTyping>
then the typed return is
jest.Mock<any, any, any>
which satisfies the constraint and allows the developer to mock the implementations anyway they like.
Is there a way to extend my typing to be ‘but not jest.Mock<any, any, any>
‘?