openapi-typescript icon indicating copy to clipboard operation
openapi-typescript copied to clipboard

The mock setup example can not infer response bodies with disjunct content-types

Open kmoschcau opened this issue 2 years ago • 0 comments

Description

The mock setup example given in the documentation pages does not infer the parameter type for mockResponses correctly when two different status codes in the schema return different content types.

In my case this happened when I had a 200 returning an "application/json" and a 400 returning an "application/problem+json".

From some fiddling around, the point where it breaks seems to be the keyof Obj in FilterKeys. Using keyof on a union of objects with non-overlapping keys returns never.

Reproduction

// type helpers — ignore these; these just make TS lookups better
type FilterKeys<Obj, Matchers> = {
  [K in keyof Obj]: K extends Matchers ? Obj[K] : never;
}[keyof Obj];
type PathResponses<T> = T extends { responses: any } ? T["responses"] : unknown;
type OperationContent<T> = T extends { content: any } ? T["content"] : unknown;
type MediaType = `${string}/${string}`;
type MockedResponse<T, Status extends keyof T = keyof T> = FilterKeys<
  OperationContent<T[Status]>,
  MediaType
> extends never
  ? { status: Status; body?: never }
  : {
      status: Status;
      body: FilterKeys<OperationContent<T[Status]>, MediaType>;
    };

// additional repro stuff, not from the example
type Rs = {
  200: {
    content: {
      "application/json": {
        jwt?: string;
      };
    };
  };
  400: {
    content: {
      "application/problem+json": {
        statusCode?: number;
        message?: string;
        errors?: {
          [key: string]: string[];
        };
      };
    };
  };
  403: {
    content: never;
  };
  500: {
    content: never;
  };
};
type Oc = OperationContent<Rs[200 | 400]>;
type K = keyof Oc;
type Ks = FilterKeys<Oc, MediaType>;
type Mrs = MockedResponse<Rs, 200>;
type Mrs2 = MockedResponse<Rs, 400>;
type Mrs3 = MockedResponse<Rs>;

Observe:

  • Oc is a union of objects with non-overlapping keys
  • K and Ks is never
  • Mrs and Mrs2 can resolve their respective bodies
  • Mrs3 can not

Expected result

The bodies should be resolved.

Checklist

  • [X] I’m willing to open a PR (see CONTRIBUTING.md) (Provided I figure out a better way to overcome this obstacle than just adding a generic param to mockResponses and passing that to MockedResponse in its parameter.)

kmoschcau avatar Oct 18 '23 18:10 kmoschcau