Skip to content

Instantly share code, notes, and snippets.

@dwjohnston
Created June 27, 2024 00:41
Show Gist options
  • Save dwjohnston/0a0ddc58190a5caefe387d89019d61d2 to your computer and use it in GitHub Desktop.
Save dwjohnston/0a0ddc58190a5caefe387d89019d61d2 to your computer and use it in GitHub Desktop.
attempt at a MockedService utility type
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-explicit-any */
type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
type IsAny<T, Y, N> = IfAny<T, Y, N>;
type TypeWithGeneric<T> = T[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// type extractGeneric<Type> =
// Type extends jest.MaybeMockedDeep<infer X, any[], any> ? X : never;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type JestMockAny = jest.Mock<any, any, any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type JestMockString = jest.Mock<string, number[], null>;
type IsJestMockAny<T extends jest.MockableFunction> = IsAny<
ReturnType<T>,
never,
jest.MaybeMockedDeep<T>
>;
const fn = jest.fn<string, number[], any>();
const result = fn(1, 2, 3);
type A = IsJestMockAny<JestMockAny>;
type B = IsJestMockAny<JestMockString>;
const b: B = (a, b) => {};
export type MockedService<
T extends Record<string | symbol | number, jest.MockableFunction>
> = {
// https://stackoverflow.com/questions/78674994/is-there-way-to-say-but-doesnt-match-any-in-typescript/78675024#78675024
[K in keyof T]: IsJestMockAny<T[K]>;
} & T;
type Foo = {
getA: (a: string, b: string) => Promise<{ c: string }>;
getB: (e: number, f: number) => Promise<{ g: string }>;
};
const mockedFoo: 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()
};
function createMockedService<
T extends Record<string | symbol | number, jest.MockableFunction>,
V extends MockedService<T>
>(value: V) {
return value;
}
createMockedService<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()
});
mockedFoo.getB(1, 2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment