msw icon indicating copy to clipboard operation
msw copied to clipboard

Issue with response resolver types after recent upgrade

Open joeldotsh opened this issue 1 year ago • 5 comments

Hi,

Love MSW thanks for all your hard work!

I'm struggling with types and hoping there's a simple tweak here.

We have a light abstraction over server.use for usage in our tests:

type MockApiArgs<
  RequestBodyType extends DefaultBodyType = DefaultBodyType,
  ResponseBodyType extends DefaultBodyType = undefined,
> = {
  server: SetupServer | SetupWorker;
  method: "get" | "post" | "patch" | "put" | "delete";
  endpoint: string;
  response?: ResponseBodyType;
  status?: number;
  resolverCb?: ResponseResolver<
    HttpRequestResolverExtras<PathParams>,
    RequestBodyType,
    ResponseBodyType
  >;
};

export function mockApi<
  RequestBodyType extends DefaultBodyType = DefaultBodyType,
  ResponseBodyType extends DefaultBodyType = undefined,
>({
  server,
  method,
  endpoint,
  response,
  status = 200,
  resolverCb,
}: MockApiArgs<RequestBodyType, ResponseBodyType>) {
  server.use(
    http[method]<PathParams, RequestBodyType, ResponseBodyType>(
      `*${endpoint}`,
      async (info) => {
        const ret = HttpResponse.json(response, {
          status,
        });

        if (resolverCb) {
          await resolverCb(info);
        }

        return ret;
      }
    )
  );
}

We were just on 2.2.10 where it was working fine, and now seeing a type error on the resolverCb callback:

  Type 'Promise<StrictResponse<JsonBodyType>>' is not assignable to type 'AsyncResponseResolverReturnType<ResponseBodyType>'.
    Type 'Promise<StrictResponse<JsonBodyType>>' is not assignable to type 'Promise<ResponseResolverReturnType<ResponseBodyType> | Generator<MaybeAsyncResponseResolverReturnType<ResponseBodyType>, MaybeAsyncResponseResolverReturnType<...>, MaybeAsyncResponseResolverReturnType<...>>>'.
      Type 'StrictResponse<JsonBodyType>' is not assignable to type 'ResponseResolverReturnType<ResponseBodyType> | Generator<MaybeAsyncResponseResolverReturnType<ResponseBodyType>, MaybeAsyncResponseResolverReturnType<...>, MaybeAsyncResponseResolverReturnType<...>>'.
        Type 'StrictResponse<JsonBodyType>' is not assignable to type '[ResponseBodyType] extends [undefined] ? Response : StrictResponse<ResponseBodyType>'.ts(2345)

For context, the helper is called like so:

    mockApi<MyRequestType>({
      server,
      method: "post",
      endpoint: "foo",
      resolverCb: async ({ request }) => {
        // working type inference on request as MyRequestType
      },
    });

Any insight is appreciated, thanks!

joeldotsh avatar Apr 01 '24 17:04 joeldotsh

I'm seeing a similar error with the latest version. I'm mocking all graphql operations against a schema as defined in the docs: https://mswjs.io/docs/recipes/mock-graphql-schema , but that exact code snippet doesn't pass the typescript check. The error is :

Argument of type '({ query, variables }: ResponseResolverInfo<GraphQLResolverExtras<GraphQLVariables>, null>) => Promise<StrictResponse<JsonBodyType>>' is not assignable to parameter of type 'ResponseResolver<GraphQLResolverExtras<GraphQLVariables>, null, GraphQLResponseBody<GraphQLQuery>>'.
  Type 'Promise<StrictResponse<JsonBodyType>>' is not assignable to type 'AsyncResponseResolverReturnType<GraphQLResponseBody<GraphQLQuery>>'.
    Type 'Promise<StrictResponse<JsonBodyType>>' is not assignable to type 'Promise<ResponseResolverReturnType<GraphQLResponseBody<GraphQLQuery>> | Generator<MaybeAsyncResponseResolverReturnType<GraphQLResponseBody<GraphQLQuery>>, MaybeAsyncResponseResolverReturnType<...>, MaybeAsyncResponseResolverReturnType<...>>>'.
      Type 'StrictResponse<JsonBodyType>' is not assignable to type 'ResponseResolverReturnType<GraphQLResponseBody<GraphQLQuery>> | Generator<MaybeAsyncResponseResolverReturnType<GraphQLResponseBody<GraphQLQuery>>, MaybeAsyncResponseResolverReturnType<...>, MaybeAsyncResponseResolverReturnType<...>>'.
        Type 'StrictResponse<JsonBodyType>' is not assignable to type 'StrictResponse<GraphQLResponseBody<GraphQLQuery>>'.
          Type 'JsonBodyType' is not assignable to type 'GraphQLResponseBody<GraphQLQuery>'.
            Type 'string' has no properties in common with type 'GraphQLResponseBody<GraphQLQuery>'

I suspect this stems from the change in https://github.com/mswjs/msw/pull/2107

glenn-vandeputte avatar Apr 03 '24 08:04 glenn-vandeputte

Update: I was able to fix the type errors by adjusting http[method]<PathParams, RequestBodyType, ResponseBodyType>(...) to http[method]<PathParams, RequestBodyType, JsonBodyType>(...). I guess the issue came down to trying to return HttpResponse.json(response, { status, });, which has a type of JsonBodyType that was incompatible with DefaultBodyType

Not sure if this is totally right, but in terms of how I'm using this (wanting type inference working via mockApi<MyRequestType>(...)), it does the trick

joeldotsh avatar Apr 18 '24 07:04 joeldotsh

Unsure if this is related, but I was seeing this issue if I had an arrow function return instead of just returning the HttpResponse method.

E.g. this has the error

        http.post('URL_PATH', async () => {
          await delay();
          return () => HttpResponse.json({value: 'error'}, {status: 400});
        }),

But this does not

        http.post('URL_PATH', async () => {
          await delay();
          return HttpResponse.json({value: 'error'}, {status: 400});
        }),

deansimcox avatar Jul 25 '24 01:07 deansimcox