Search code examples
typescriptprotocol-buffersgrpcgrpc-node

Compiled Typescript files from gRPC proto files mark every property as optional


I have a bunch of proto files that I compiled to Typescript with the following script:

yarn proto-loader-gen-types \
    --grpcLib=@grpc/grpc-js \
    --outDir=${OUT_DIR} \
    ${IN_DIR}/*.proto

One of the messages defined is Bool:

message Bool {
  bool state = 1;
}

When I look at the compiled Typescript files, ALL of the object properties are defined as optional.

export interface Bool {
  'state'?: (boolean);
}

export interface Bool__Output {
  'state'?: (boolean);
}

I've been writing tests and when I expect true I seem to be getting the expected object { state: true } but when I'm expecting false, I get an empty object {} instead of the object shape that I expect { state: false }.

How do I compile my proto files to Typescript and make sure that non-optional properties are actually defined as such?


Solution

  • The message interfaces generated by the proto-loader-gen-types tool are intended for use with the corresponding service interfaces, and represent objects that will be used with the corresponding runtime generated code. The "permissive" interfaces without the __Output suffix represent the types of objects that can be created by the user and passed to the library, and the "restrictive" interfaces with the __Output suffix represent the types of objects that the library will provide to the user.

    All fields in "permissive" interfaces are optional because the library will accept input objects with those fields omitted, and will use the default values. By default, all fields in the "restrictive" interfaces are also optional because the library will output objects without those fields if they have their default values. The options defaults, arrays, and objects change that behavior for primitive fields, repeated fields, and message fields respectively.

    Keep in mind that in Protobuf 3, all fields are effectively optional, in a sense. Any field can be omitted from a serialized message, and that is treated as its default value. The object representation that the @grpc/proto-loader library uses reflects that.