Skip to content

Error type incorrectly inferred #2343

Open
@CynicalBusiness

Description

@CynicalBusiness

openapi-react-query version

0.5.0

Description

The error types for all query/mutation methods, including queryOptions, is inferred incorrectly and always results in undefined (or null | undefined).

The example provided in the documentation, therefor, does not work.

Copied from https://openapi-ts.dev/openapi-react-query/#basic-usage and modified only to attach it to my generated openapi schema (which was generated by openapi-typescript).

import createFetchClient from "openapi-fetch";
import createClient from "openapi-react-query";
import type { paths } from "./api.schema.gen.js"; // generated by openapi-typescript

const fetchClient = createFetchClient<paths>({
  baseUrl: "https://myapi.dev/v1/",
});
const $api = createClient(fetchClient);

const MyComponent = () => {
  const { data, error, isLoading } = $api.useQuery(
    "get",
    "/projects/id={projectId}",
    {
      params: {
        path: { projectId: "fake-uuid" },
      },
    },
  );

  if (isLoading || !data) return "Loading...";

  if (error) return `An error occured: ${error.message}`; // !! Property 'message' does not exist on type 'never'. ts(2339)

  return <div>{data.title}</div>;
};

And the editor hover-over indicates error is null | undefined, so the error makes sense:
Image

The null arrives from react-query itself, but the undefined is a problem, and it also appears in both the onError callback and error state of mutations as only undefined.

For reference, here is the underlying path from openapi.yaml, as generated by @nestjs/swagger:

paths:
# ...
  /projects/id={projectId}:
    get:
      description: Gets a project by its ID
      operationId: ProjectsByIdController_get
      parameters:
        - name: projectId
          required: true
          in: path
          description: The project ID
          schema:
            format: uuid
            type: string
      responses:
        "200":
          description: The project
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ProjectModel"
        "403": &a3
          description: User is not authorized to perform this action.
        "404": &a4
          description: The project requested could not be found.
      summary: ""
      tags: &a5
        - projects

My thoughts as to possible sources of the error are:

  • The types UseMutationMethod, UseQueryMethod, etc. get the error via the generic Response["error"], but Response is a FetchResponse, which is a union type, and only the first member of the union is extracted (which is undefined | never and the never gets dropped by TS). Based on TypeScript 5.8. Edit: Never mind this, fairly confident it's the next thing.
  • The ErrorResponse and GetResponseContent from openapi-typescript-helpers expected a content block to be present on the error and ignores errors which do not have them.

Regardless of which of the two is correct, other errors not present in the schema can still occur, such as undocumented responses (mainly 5xx) or network errors. IMO, the error type should at least always include Error to indicate otherwise-undocumented errors (who's to say a TypeError or deserialization errors won't appear?), or just become unknown as is usually the case in JS.

Edit: This following yarn patch alleviates the problem by introducing Error as suggested and gets things working again.

openapi-fetch-npm-0.14.0-20e667e085.patch
diff --git a/dist/index.d.mts b/dist/index.d.mts
index d0bdd6b4e2ff6a89cf2014b533b37bb16abb8a44..a8e176b53ec4e32c376067d6e00a62699b10ad14 100644
--- a/dist/index.d.mts
+++ b/dist/index.d.mts
@@ -97,7 +97,7 @@ type FetchResponse<T extends Record<string | number, any>, Options, Media extend
     }
   | {
       data?: never;
-      error: ErrorResponse<ResponseObjectMap<T>, Media>;
+      error: ErrorResponse<ResponseObjectMap<T>, Media> | Error;
       response: Response;
     };

Reproduction

The snippets above reproduce the error when copy & pasted in under TypeScript 5.8.

Expected result

The error does not appear, as documented.

Extra

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingopenapi-react-queryRelevant to openapi-react-query

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions