Typing gRPC with Node & Typescript

I use gRPC from my graphQL gateway to call gRPC servers. This gql server is written in Node using Typescript, and obviously I want to use the power and safety of TS types for it!

I will show and explain the tool I use to generate the TS types from the .proto definition and a couple of examples with those types.

The tool in question is protobuf.

protobuf.js is a pure JavaScript implementation with TypeScript support for node.js and the browser. It’s easy to use, blazingly fast and works out of the box with .proto files!

I’ve found that to make it work seamlessly with typescript, I need to generate both the javascript and the types from my .proto .

To do this, we will use the 2 client binaries that come with protobuf: pbjs and pbts:

Generating the javascript

Run

pbjs -t static-module -w commonjs -o path/2/your/new/generated/service.js path/2/your/Something.proto

This will create the implementation of the types that you will create in the following step.

Generating the Typescript definitions

Run

pbjs -t static-module path/2/your/Something.proto | pbts -o path/2/your/new/generated/ts/service.d.ts -

This command is generating the javascript on the fly and passing it to pbts . If you want, you can use the already generated javascript with this command:

pbts -o compiled.d.ts path/2/your/compiled.js

Now your favorite IDE should understand the types generated from the .proto definitions. And most of all, you can use the types that we all love!

Example of usage

import { com } from ' path/2/your/generated/ts/protoService ' ; import grpc , { GrpcObject } from ' grpc ' ; const PROTO_PATH = path . join ( process . cwd (), ' path/2/your/Something.proto ' ); const protoDescriptor : GrpcObject = grpc . load ( PROTO_PATH ); // @ts-ignore: the nested grpc objects are not recognized by ts, if anyone can help me here, thanks :) const SomethingService = protoDescriptor . com . proto . SomethingService ; const serviceImpl : protoDescriptor . com . proto . SomethingService = new SomethingService ( /**/ ); // this serviceImpl has all the methods and types included in the .proto!

I had to extract this example from an app of mine so hopefully it’s understandable enough to show you that you can get a typed service and that then you can use it to call the methods, check the types and test more safely your service.

Let me know if it helps, or if you have any kind of feedback,

Cheers! :)