connectrpc / connect-query-es

TypeScript-first expansion pack for TanStack Query that gives you Protobuf superpowers.
https://connectrpc.com/docs/web/query/getting-started
Apache License 2.0
239 stars 17 forks source link

Possible type-error: Types of property 'kind' are incompatible when using useQuery #387

Closed alexongh closed 3 months ago

alexongh commented 4 months ago

Abstract I am currently running a test using @connectrpc/connect-query-es in a test Next.js application. It works, but I am getting an error from tsserver.

Versions Next.js: 13.5.6 @connect/connect-query: 1.4.1

Details

Error message:

Diagnostics:
1. Argument of type '{ localName: string; name: string; kind: MethodKind; I: MessageType<AnyMessage>; O: MessageType<AnyMessage>; idempotency: MethodIdempotency; service: { ...; }; }' is not assignable to parameter of type 'MethodUnaryDescriptor<Message<unknown>, Message<unknown>>'.
     Type '{ localName: string; name: string; kind: MethodKind; I: MessageType<AnyMessage>; O: MessageType<AnyMessage>; idempotency: MethodIdempotency; service: { ...; }; }' is not assignable to type 'MethodInfoUnary<Message<unknown>, Message<unknown>>'.
       Types of property 'kind' are incompatible.
         Type 'MethodKind' is not assignable to type 'MethodKind.Unary'. [2345]

Generated code (located in src/gen/services/tests/v1/*):

import { MethodIdempotency, MethodKind } from "@bufbuild/protobuf";
import { ViewRequest, ViewResponse } from "./tests_pb.js";

export const view = {
  localName: "view",
  name: "View",
  kind: MethodKind.Unary,
  I: ViewRequest,
  O: ViewResponse,
      idempotency: MethodIdempotency.NoSideEffects,
  service: {
    typeName: "services.tests.v1.TestService"
  }
};

Used as follows:

import { view } from "src/gen/services/tests/v1/tests-TestService_connectquery" 
import { useQuery } from "@connectrpc/connect-query";

// (...)

const data = useQuery(view) 

tsconfig.json

{
  "compilerOptions": {
    "target": "es2017",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "checkJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "noUncheckedIndexedAccess": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./src/*"
      ]
    },
    "plugins": [
      {
        "name": "next"
      }
    ]
  },
  "include": [
    ".eslintrc.cjs",
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.cjs",
    "**/*.mjs",
    ".next/types/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "src/gen/*"
  ]
}

As mentioned: Functionally all of this works. I did some digging and if I manually edit the generated file to kind: 0 instead of kind: MethodKind.Unary the error disappears :heavy_check_mark:.

I don't understand why this error occurs, or if this even is an error in connectrpc/connect-query-es, or if I messed up. To me packages/connect-query/src/method-unary-descriptor.ts and related type definitions seem to be defined correctly.

timostamm commented 4 months ago

Hey Alex, at the top of the generated _connectquery.ts file, do you see a line // @ts-nocheck?

Please try to delete this line, and see if the error message changes. I suspect there's an underlying issue resolving the import from @bufbuild/protobuf. You can disable the line with the plugin option ts_nocheck=false - see the link for context.

alexongh commented 4 months ago

Hi Timo. Yes, there is a // @ts-nocheck in the generated file. I tried removing it and the problem persisted. I also regenerated the files with the ts_nocheck=false option set on protoc-gen-es and protoc-gen-connect-query and the problem persisted unfortunately.

Tsserver Version: 4.3.3 Installed via Mason running in Neovim version 0.9.5

timostamm commented 4 months ago

Removing @ts-nocheck will not fix any issues, but I expected it to show a different error message. Since removing it didn't change the error message, it's not relevant, but I recommend to keep removing it with the plugin option.

I'd check for multiple versions of @bufbuild/protobuf in your project, and I'd try to remove this line from your config:

  "exclude": [
    "node_modules",
-   "src/gen/*"
  ]

If this doesn't help, please share a reproducible example 🙂

alexongh commented 4 months ago

Removing "src/gen/*" from tsconfig.json didn't resolve the issue, so I created an example. The example is structured in the same way the issue arose, and it arises within this issue.

It covers three repositories:

The (same) issue arises in /src/app/page.tsx at the useQuery call.

2024-07-10_22-25

timostamm commented 3 months ago

Ah, you are using JavaScript files without type declarations. TypeScript has become decent at that, but there are many situations where it isn't able to infer types, and you found one.

To fix the issue, make the following change to your buf.gen.yaml file:

 version: v2
 plugins:
   - local: protoc-gen-es
     out: src/gen
     opt: 
-     - target=js
+     - target=ts
      - ts_nocheck=false
   - local: protoc-gen-connect-query
     out: src/gen
     opt: 
-     - target=js
+     - target=ts
      - ts_nocheck=false

Then run:

$ rm -rf src/gen/*
$ npm run buf:generate

This generates TypeScript files instead of JavaScript files. Alternatively, you can use target=js+dts or simply remove the option, which is the same. See https://github.com/bufbuild/protobuf-es/tree/v1.10.0/packages/protoc-gen-es#target for details.

alexongh commented 3 months ago

Ah, you are using JavaScript files without type declarations. TypeScript has become decent at that, but there are many situations where it isn't able to infer types, and you found one.

To fix the issue, make the following change to your buf.gen.yaml file:

 version: v2
 plugins:
   - local: protoc-gen-es
     out: src/gen
     opt: 
-     - target=js
+     - target=ts
      - ts_nocheck=false
   - local: protoc-gen-connect-query
     out: src/gen
     opt: 
-     - target=js
+     - target=ts
      - ts_nocheck=false

Then run:

$ rm -rf src/gen/*
$ npm run buf:generate

This generates TypeScript files instead of JavaScript files. Alternatively, you can use target=js+dts or simply remove the option, which is the same. See https://github.com/bufbuild/protobuf-es/tree/v1.10.0/packages/protoc-gen-es#target for details.

This fixed the issue. Thank you very much! Maybe this issue is something for a troubleshooting page. I can see other people running into the same issue, but this is your call