ts-proto
ts-proto copied to clipboard
Using a well-known type inside a RPC argument results in weird code generation
Currently we are trying to generate Typescript files out of our proto files to use them in our frontend. We have a gRPC file with the following:
...
rpc GetApp (google.protobuf.Int32Value) returns (App);
...
This results into the following generated code:
...
GetApp(request: DeepPartial<number>, metadata?: grpc.Metadata): Promise<App> {
return this.rpc.unary(
ServiceGetAppDesc,
number.fromPartial(request), // <---
metadata
);
}
...
As you can see in the sample above, the generated code calls a function on a primitive js type, which results in an error:
semantic error TS2693: 'number' only refers to a type, but is being used as a value here.
We use these arguments:
--ts_proto_opt=esModuleInterop=true
--ts_proto_opt=env=web
--ts_proto_opt=useOptionals=true
--ts_proto_opt=oneof=unions
--ts_proto_opt=unrecognizedEnum=false
--ts_proto_opt=outputClientImpl=grpc-web
--ts_proto_opt=fileSuffix=.pb
Hm, yeah, so that part of the output comes from:
https://github.com/stephenh/ts-proto/blob/main/src/generate-grpc-web.ts#L64
And we can inputType
from:
const inputType = requestType(ctx, methodDesc);
Which uses methodDesc.inputType
(which is normally .package.SomeMessage
) to resolve that into an import
-able type.
I don't think we have an existing way to detect whether the return type of requestType
is a primitive or not, but you could probably make an isPrimitive(ctx, typeName)
helper method that uses ctx.typeName
to see if typeName
is in the map, and if it is, it's a message, and if it's not, it should be a primitive.
I.e. add a condition like:
const usePartial = isPrimitive(ctx, methodDesc.inputType);
And then use that to adjust the contents of partialInputType
.
I don't have time to personally flush this out more than that, but hopefully that's enough pointers to get a PR going if you'd like to fix it. Thanks!