How to force typescript to interpret a parameter as a namespace instead of a class when they have the same name - gRPC

Asked

Viewed 155 times

-3

I am implementing a small crud using gRPC and typescript, my problem is: The self-generated stubs create a class and a "type" for each parameter in the protofile. For example, the Userid parameter generates a class with getUserId, etc, and a namespace with "type" Userid.

The problem is that when I try to use the method in mine client, typescript interprets the method parameter as the class and not the type.

So instead of getUsersById({id: 1}, callback)... he asks me something like getUsersById(new UserId).

user. Proto:

syntax = "proto3";

package userServicePKG;

message User {
    int32 id = 1;
    string name = 2;
    int32 age = 3;
}

message UserId {
    int32 id = 1;
}

service UserService{
    rpc getUserById (UserId) returns (User);
}

Userserviceclientpb.ts (Protobuf generated) - Function Definition

methodInfogetUserById = new grpcWeb.AbstractClientBase.MethodInfo(
    User,
    (request: UserId) => {
      return request.serializeBinary();
    },
    User.deserializeBinary
  );

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null): Promise<User>;

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null,
    callback: (err: grpcWeb.Error,
               response: User) => void): grpcWeb.ClientReadableStream<User>;

  getUserById(
    request: UserId,
    metadata: grpcWeb.Metadata | null,
    callback?: (err: grpcWeb.Error,
               response: User) => void) {
    if (callback !== undefined) {
      return this.client_.rpcCall(
        new URL('/userServicePKG.UserService/getUserById', this.hostname_).toString(),
        request,
        metadata || {},
        this.methodInfogetUserById,
        callback);
    }
    return this.client_.unaryCall(
    this.hostname_ +
      '/userServicePKG.UserService/getUserById',
    request,
    metadata || {},
    this.methodInfogetUserById);
  }

user_pb.d.ts (Protobuf Generated) - Defines types and Classes:

export class UserId extends jspb.Message {
  getId(): number;
  setId(value: number): UserId;

  serializeBinary(): Uint8Array;
  toObject(includeInstance?: boolean): UserId.AsObject;
  static toObject(includeInstance: boolean, msg: UserId): UserId.AsObject;
  static serializeBinaryToWriter(message: UserId, writer: jspb.BinaryWriter): void;
  static deserializeBinary(bytes: Uint8Array): UserId;
  static deserializeBinaryFromReader(message: UserId, reader: jspb.BinaryReader): UserId;
}

export namespace UserId {
  export type AsObject = {
    id: number,
  }
}

Client.Vue:

const client = new UserServiceClient('http://localhost:5001', null, null);

let userId = { id:1 };
client.getUserById(userId, function (error: grpcWeb.Error, response: any) {
     //do something
});

The userid parameter causes the following error:

Argument of type '{ id: number; }' is not Assignable to Parameter of type 'Userid'. Type '{ id: number; }' is Missing the following properties from type 'Userid': getId, setId, serializeBinary, toObject, and 8 more. Vetur(2345)

It seems to me that typescript deduces that the first parameter getUserById is the type Class UserId and not the kind that comes from namespace UserId.

Is there anything I can do about it? Since it was self-generated code by grpc_web, it should interpret correctly right? Oh it is not a mistake of mine in the implementation of gRPC or misuse of typescript.

Thanks in advance!

  • Thank you for indicating problems with the question too, thank you.

  • The answer is in the error message. When you do this let userId = { id:1 };&#xA;client.getUserById(userId, function (error: grpcWeb.Error, response: any) {&#xA; //do something&#xA;}); this variable userId is not an instance of UserId and therefore cannot be passed as a parameter to this function. Create a class instance, as a reader I cannot do this because the question does not provide enough information to instantiate the class UserId does not show the constructor and I know 5 libs that have the type jspb.Message, that UserId drift and all different, making it impossible to answer.

  • @Augustovasques Thank you so much for your help, jspb.Message comes from the following import import * as jspb from "google-protobuf", will help in something?

  • The manual says to instantiate and not subclass jspb.Message. You’ll have to modify the function.

1 answer

2


You need to correctly type your userid variable. When you do {} to instantiate an object, it will be of type Object. Do:

let userId: UserId = new UserId().setId(1); // Tipado como UserId

client.getUserById(userId, function (error: grpcWeb.Error, response: any) {
    //do something
});
  • You’re right, I had found the answer but I just didn’t have time to answer here. Even this link here helped me a lot https://grpc.io/docs/platforms/web/basics/ . The big problem is that most online tutorials explain grpc clients in other technologies and not gRPC web, because it is still very new. Thank you very much for your reply.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.