How to determine which fields are optional, from typescript interfaces generated from GRPC proto-files?

761 views Asked by At

In a ts-node project, I'm generating TypeScript from gRPC proto files, where some properties are marked as optional.

However, the resulting TS interfaces have ALL properties marked as optional. And then an extra "_" prefixed property for the property that's actually optional?

What I need is just a way to check in my TS code, whether a field is optional or not (so I can skip the undefined checks etc), but I find it hard to do with this generated code.

Is there a way to fix this or maybe tweak the code generation?

(Proto version 3)

message GetStatusResponse {
    OperationMode mode = 1;
    optional string transactionId = 2;
    SystemState state = 3;
    string systemName = 4;
}

// Original file: proto/autofuel.proto

import type { OperationMode as _autofuel_control_OperationMode, OperationMode__Output as _autofuel_control_OperationMode__Output } from '../../autofuel/control/OperationMode';
import type { SystemState as _autofuel_control_SystemState, SystemState__Output as _autofuel_control_SystemState__Output } from '../../autofuel/control/SystemState';

export interface GetStatusResponse {
  'mode'?: (_autofuel_control_OperationMode);
  'transactionId'?: (string);
  'state'?: (_autofuel_control_SystemState);
  'systemName'?: (string);
  '_transactionId'?: "transactionId";
}

export interface GetStatusResponse__Output {
  'mode'?: (_autofuel_control_OperationMode__Output);
  'transactionId'?: (string);
  'state'?: (_autofuel_control_SystemState__Output);
  'systemName'?: (string);
}

I was expecting something like this:

export interface GetStatusResponse {
  mode: _autofuel_control_OperationMode;
  transactionId: string;
  state: _autofuel_control_SystemState;
  systemName: string;
}

The command I use for generating:

proto-loader-gen-types --grpcLib=@grpc/grpc-js --outDir=proto/generated/ proto/*.proto

My package.json:

{
  "name": "machine-ui-gateway",
  "version": "0.0.1",
  "main": "main.ts",
  "license": "MIT",
  "dependencies": {
    "@grpc/grpc-js": "^1.8.0",
    "@grpc/proto-loader": "^0.7.4",
    "async-mqtt": "^2.6.3",
    "dotenv": "^16.0.3",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.14",
    "nodemon": "^2.0.20",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.4"
  },
  "scripts": {
    "build": "tsc",
    "start": "nodemon main.ts",
    "proto:gen": "proto-loader-gen-types --grpcLib=@grpc/grpc-js --outDir=proto/generated/ proto/*.proto"
  }
}

1

There are 1 answers

1
dokgu On

I came across this issue and was able to partially solve it by adding the --defaults flag when compiling proto files to Typescript. See my more detailed answer here: https://stackoverflow.com/a/75621525/5530965

--objects

Output default values for omitted message fields even if --defaults is not set [boolean] [default: false]

Unfortunately this only marks the object properties on the __Output interface as being mandatory. It's a start!