如何强制打字稿将参数解释为名称空间而不是 class,当它们具有相同的名称时 - gRPC
How to force typescript to interpret a parameter as a namespace rather than a class, when they have the same name - gRPC
抱歉标题太长...
我正在使用 gRPC 和 typescript 实现一个简单的 crud 小系统,我的问题是:自动生成的文件为我的 protoFile
中的每个参数创建一个 class 和一个类型,例如: UserId 参数生成带有 getUserId 等的 class,以及类型为 UserId 的命名空间。
问题是,当我尝试在 client
中使用该方法时,打字稿需要 class 作为参数,而不是类型。
所以而不是 getUsersById({id: 1}, callback)
... 它要求我做 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)- 函数定义
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 生成)- 定义类型和 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
});
参数 userId 引发以下错误:
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)
在我看来,typescript 推断 getUserById
第一个参数是 Class UserId
类型,而不是来自 命名空间 UserId
.
有什么我可以做的吗?由于它是自动生成的,我觉得它应该正确解释?我在搞砸其他事情吗?我是 gRPC 的新手,所以我可能做错了什么。
提前致谢!
消息 UserId
生成为 JavaScript class。您必须提供此 class 的一个实例,实际上没有其他选择,至少对于 protoc-gen-grpc-web 生成的代码而言没有。
有一些基于 TypeScript 的替代代码生成器不需要您使用 classes。 ts-proto 和 protobuf-ts 使用简单的接口而不是 classes 来表示消息。 (我是protobuf-ts的作者)
例如,protobuf-ts 从您的 user.proto 生成代码,可以像这样使用:
// gRPC-web provided by @protobuf-ts/grpcweb-transport
const transport = new GrpcWebFetchTransport("http://localhost:5001");
const client = new UserServiceClient(transport);
const {response} = await client.getUserById({id: 123});
console.log(
response.id,
response.name,
response.age
);
我想 ts-proto 前段时间也得到了 grpc-web 的支持。也许试一试,看看您是否更喜欢生成的代码。
抱歉标题太长...
我正在使用 gRPC 和 typescript 实现一个简单的 crud 小系统,我的问题是:自动生成的文件为我的 protoFile
中的每个参数创建一个 class 和一个类型,例如: UserId 参数生成带有 getUserId 等的 class,以及类型为 UserId 的命名空间。
问题是,当我尝试在 client
中使用该方法时,打字稿需要 class 作为参数,而不是类型。
所以而不是 getUsersById({id: 1}, callback)
... 它要求我做 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)- 函数定义
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 生成)- 定义类型和 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
});
参数 userId 引发以下错误:
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)
在我看来,typescript 推断 getUserById
第一个参数是 Class UserId
类型,而不是来自 命名空间 UserId
.
有什么我可以做的吗?由于它是自动生成的,我觉得它应该正确解释?我在搞砸其他事情吗?我是 gRPC 的新手,所以我可能做错了什么。
提前致谢!
消息 UserId
生成为 JavaScript class。您必须提供此 class 的一个实例,实际上没有其他选择,至少对于 protoc-gen-grpc-web 生成的代码而言没有。
有一些基于 TypeScript 的替代代码生成器不需要您使用 classes。 ts-proto 和 protobuf-ts 使用简单的接口而不是 classes 来表示消息。 (我是protobuf-ts的作者)
例如,protobuf-ts 从您的 user.proto 生成代码,可以像这样使用:
// gRPC-web provided by @protobuf-ts/grpcweb-transport
const transport = new GrpcWebFetchTransport("http://localhost:5001");
const client = new UserServiceClient(transport);
const {response} = await client.getUserById({id: 123});
console.log(
response.id,
response.name,
response.age
);
我想 ts-proto 前段时间也得到了 grpc-web 的支持。也许试一试,看看您是否更喜欢生成的代码。