Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript Type Check Errors #279

Closed
purebluesong opened this issue Sep 3, 2018 · 18 comments
Closed

Typescript Type Check Errors #279

purebluesong opened this issue Sep 3, 2018 · 18 comments

Comments

@purebluesong
Copy link

purebluesong commented Sep 3, 2018

Some errors exposed when I try to compile my generated typescript code.

One error message here:

Argument of type '(request: Empty) => Uint8Array' is not assignable to parameter of type '(request: {}) => {}'.
  Types of parameters 'request' and 'request' are incompatible.
    Type '{}' is not assignable to type 'Empty'.
      Property 'serializeBinary' is missing in type '{}'.

And I found the generation code is here:

"new grpcWeb.AbstractClientBase.MethodInfo(\n");

Another error message here:

Argument of type '(err: Error, response: Empty) => void' is not assignable to parameter of type '(err: Error, response: {}) => void'.
  Types of parameters 'response' and 'response' are incompatible.
    Type '{}' is not assignable to type 'Empty'.

And I found the generation code is here:

The part of the wrong generated code shows here:

methodInfoSome = new grpcWeb.AbstractClientBase.MethodInfo(
    Empty,
    (request: SomeRequest) => {  // Here is the first error
      return request.serializeBinary();
    },
    Empty.deserializeBinary
  );

  some(
    request: SomeRequest,
    metadata: grpcWeb.Metadata,
    callback: (err: grpcWeb.Error,
               response: Empty) => void) {
    return this.client_.rpcCall(
      this.hostname_ +
        '/SomePath',
      request,
      metadata,
      this.methodInfoSome,
      callback); // Here is the second error which the callback is `(err: Error, response: Empty) `
  }

The Empty message defined in proto file likes this message Empty {}
FYI: My TS version is 3.0.1

@stanley-cheung
Copy link
Collaborator

I am not quite able to reproduce. Can you show me your .proto file, preferably a little simplified to illustrate the error, and perhaps an entry point client.ts?

@purebluesong
Copy link
Author

The proto is here:

service SomeService {
    rpc Some(SomeRequest) returns (Empty) {}
}

message SomeRequest {
    string id = 1;
}

message Empty {}

And the entry point is nothing special just a useless import.

@stanley-cheung
Copy link
Collaborator

Hm, I am still missing something.

  1. I put your proto content into someservice.proto.
  2. I generate my code using protoc -I=. someservice.proto --js_out=import_style=commonjs:. --grpc-web_out=import_style=typescript,mode=grpcwebtext:.. This gives me 3 files:
  • someservice_pb.d.ts
  • someservice_pb.js
  • SomeserviceServiceClientPb.ts
  1. I made a index.ts with just an import import {SomeServiceClient} from './SomeserviceServiceClientPb';
  2. Here's my tsconfig.json
{                                                                                                             
  "compilerOptions": {                                                                                        
    "target": "es5",                                                                                          
    "module": "commonjs",                                                                                     
    "noImplicitAny": true,                                                                                    
    "declaration": true,                                                                                      
    "outDir": "./dist",                                                                                       
    "types": ["node"],                                                                                        
  },                                                                                                          
  "include": [                                                                                                
    "index.ts",                                                                                              
    "someservice_pb.js",                                                                                      
    "someservice_pb.d.ts",                                                                                    
    "SomeserviceServiceClientPb.ts"                                                                           
  ],                                                                                                          
  "exclude": [                                                                                                
    "node_modules"                                                                                            
  ]                                                                                                           
}                                                                                                             
  1. My package.json is also simple
{                                                                                                             
  "dependencies": {                                                                                           
    "@types/node": "^10.7.1",                                                                                 
    "grpc-web": "^0.4.0"
  }                                                                                                           
} 
  1. I ran tsc from the command line and there's no error.

@stanley-cheung
Copy link
Collaborator

stanley-cheung commented Sep 5, 2018

Oh, my Typescript version may not match yours

$ tsc --version                                                        
Version 2.9.2 

Hm, didn't help. I installed tsc version 3.0.3 and still compiles without error

$ npx tsc --version                                                    
Version 3.0.3 

@purebluesong
Copy link
Author

Is the generated js file necessary?Maybe I missed this output file and I will try again.

@stanley-cheung
Copy link
Collaborator

Ah yes, they are necessary.

So what happened was, there is no typescript support from protobuf yet. The protoc --js_out plugin will only output .js files. With the --grpc-web_out plugin here in this repo, we are currently outputing the minimal set of typings definitions for the protobuf message .js files.

@purebluesong
Copy link
Author

purebluesong commented Sep 5, 2018

I think this should be written into the readme, it's not so easy to understand why I must generate the js file when I only want the ts output.

@purebluesong
Copy link
Author

purebluesong commented Sep 10, 2018

Found the problem:

function test1(testfunc: (request: {}) => {}) {}
test1((request: Empty) => {return ""})

The tsc will throw this code type imcompaitable error due to the {} object assigned to Empty.
And the Empty class has attributes like serializeBinary while {} not.

So I suggest to change the generate code like this.

function test1(testfunc: (request: any) => {}) {}
test1((request: Empty) => {return ""})

Mainly diffrence is '{}' and 'any'.

Or just simply change the request type {serializeBinary(): Unit8Array} since every request object has it.

@purebluesong
Copy link
Author

purebluesong commented Sep 10, 2018

Meanwhile, the second error which describes callback is the same as above.

Here is the typescript type compatibility syntax guide. Hope it's helpful.

@stanley-cheung
Copy link
Collaborator

Actually I'd like to be able to use any in the meantime when we started out. But our internal linter doesn't like it. I will need to find some other workaround. Will keep this in mind.

@purebluesong
Copy link
Author

Any progress?

@stanley-cheung
Copy link
Collaborator

Found the problem:

function test1(testfunc: (request: {}) => {}) {}
test1((request: Empty) => {return ""})

What is this segment of code? Is it from the generated code? Or you wrote that? Sorry I was a little confused on how to reproduce that.

@purebluesong
Copy link
Author

I wrote that just for test. The generated code still is this issue's content

@purebluesong
Copy link
Author

As for the environment, I just created a little project by vue-cli and chose typescript as my development language. I don't know whether I could config something to ignore those errors because I am just a newbie for the web.

@henriiik
Copy link
Contributor

I ran into this as well, and i think it is related to typescripts strict mode.

If you are interested i can probably come up with a fix and send a PR. :)

@henriiik
Copy link
Contributor

I checked out the repo and updated ts-example/tsconfig.json to use "strict": true.

package.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "allowJs": true,
    "outDir": "./dist",
    "types": ["node"]
  },
  "include": [
    "client.ts",
    "echo_pb.js",
    "echo_pb.d.ts",
    "echo_grpc_web_pb.js",
    "echo_grpc_web_pb.d.ts",
    "EchoServiceClientPb.ts"
  ],
  "exclude": ["node_modules"]
}

When I then ran tsc I get the following errors:

$ tsc                                                                                                                                                                   client.ts:71:23 - error TS2345: Argument of type '(status: Status) => void' is not assignable to parameter of type '(...args: {}[]) => void'.
  Types of parameters 'status' and 'args' are incompatible.
    Type '{}' is not assignable to type 'Status'.
      Property 'code' is missing in type '{}'.

71     call.on('status', (status: grpcWeb.Status) => {
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

client.ts:108:23 - error TS2345: Argument of type '(response: ServerStreamingEchoResponse) => void' is not assignable to parameter of type '(...args: {}[]) => void'.
  Types of parameters 'response' and 'args' are incompatible.
    Type '{}' is not assignable to type 'ServerStreamingEchoResponse'.
      Property 'getMessage' is missing in type '{}'.

108     stream.on('data', (response: ServerStreamingEchoResponse) => {
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

client.ts:111:25 - error TS2345: Argument of type '(status: Status) => void' is not assignable to parameter of type '(...args: {}[]) => void'.
  Types of parameters 'status' and 'args' are incompatible.
    Type '{}' is not assignable to type 'Status'.

111     stream.on('status', (status: grpcWeb.Status) => {
                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

client.ts:117:24 - error TS2345: Argument of type '(err: Error) => void' is not assignable to parameter of type '(...args: {}[]) => void'.
  Types of parameters 'err' and 'args' are incompatible.
    Type '{}' is not assignable to type 'Error'.
      Property 'code' is missing in type '{}'.

117     stream.on('error', (err: grpcWeb.Error) => {
                           ~~~~~~~~~~~~~~~~~~~~~~~~~

client.ts:161:68 - error TS2345: Argument of type 'null' is not assignable to parameter of type '{}'.

161 const echoService = new EchoServiceClient('http://localhost:8080', null, null);
                                                                       ~~~~

@henriiik
Copy link
Contributor

henriiik commented Nov 6, 2018

these problems should be fixed, once a new version is released :)

@purebluesong
Copy link
Author

purebluesong commented Nov 6, 2018

thx, I have replaced all grpc-web with this grpc-web although :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants