How can one identify the optional fields in TypeScript interfaces generated from GRPC proto-files?

Within my ts-node project, I am converting TypeScript from gRPC proto files, where certain properties are denoted as optional.

However, the resulting TS interfaces end up with ALL properties being marked as optional. Additionally, an extra "_" prefixed property is created for the one that should actually be optional?

What I really need is a way to easily determine in my TS code whether a field is optional or not (to avoid unnecessary undefined checks), but navigating through this generated code proves challenging.

Is there a solution to correct this issue or perhaps customize the code generation process?

(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 had hoped for something resembling:

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

The command I utilize for generation:

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"
  }
}

Answer №1

After encountering a similar issue, I found a workaround that involved using the --defaults flag during the compilation of proto files into Typescript. For a more comprehensive explanation, check out my detailed response here: https://example.com/a/75621525/5530965

--objects

This option outputs default values for omitted message fields, even without setting --defaults [boolean] [default: false]

However, this approach only designates the object properties on the __Output interface as mandatory. It's a step in the right direction!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I am encountering unexpected behavior with NextJS's getInitialProps function, as it is giving me a compiler error stating "varName not found on type {}"

I seem to be stuck on a simple syntax issue while working with NextJs. I am attempting to perform dynamic server-side fetches using the getInitialProps pattern. However, the compiler is unable to recognize the return of getInitialProps in the regular func ...

How to Link an Observable Array to Another in Angular 2

In my Angular 2 project, I am trying to chain multiple HTTP calls together. Initially, I retrieve an array of environments with one call. For each environment, I want to make another call and create objects like firstObject[{name:"name",secondObject[stuff ...

What is the most efficient method for line wrapping in the react className attribute while utilizing Tailwind CSS with minimal impact on performance?

Is there a more efficient way to structure the className attribute when utilizing tailwind css? Which of the examples provided would have the least impact on performance? If I were to use an array for the classes and then join them together as shown in e ...

Capture all HTTP requests made by Angular2

I'm trying to find a way to intercept and modify all HTTP requests made by Angular by adding custom headers. In previous releases prior to angular2 RC5, this was achieved by extending the BaseRequestOptions like this: class MyOptions extends BaseRequ ...

Am I on track with this observation?

I am currently using the following service: getPosition(): Observable<Object> { return Observable.create(observer => { navigator.geolocation.watchPosition((pos: Position) => { observer.next(pos); observer.c ...

Cannot locate module using absolute paths in React Native with Typescript

I recently initiated a new project and am currently in the process of setting up an absolute path by referencing this informative article: https://medium.com/geekculture/making-life-easier-with-... Despite closely following the steps outlined, I'm en ...

How to extract component prop types in Vue 3 with typescript for reusability in other parts of your application

When you specify the props under the "props:" key of a Vue component, Vue can already automatically determine their types, which is quite convenient. However, I am wondering if there is an utility type in Vue that can be used to extract the props' ty ...

Using TypeScript to define callback functions within the Cordova.exec method

I'm encountering an issue with the TypeScript definition for Cordova. The codrova.d.ts file doesn't allow for any function arguments in the success-callback and error-callback. To better illustrate my problem, here's a small example: Here ...

Verify optional chaining support in Angular app for browsers

Within my Angular application, I am looking to verify if a client's browser supports optional chaining (es2020) in order to load a library that contains both a modern ES version and a legacy one. The issue arises when the Angular compiler (which I su ...

Tips for accessing the value and text of an Angular Material mat-select through the use of *ngFor

When using a dropdown menu, I want to retrieve both the value and text of the selected option. View dropdown image Underneath the dropdown menu, I aim to display values in the format of "options: 'value' - 'selected option'". compone ...

Rxjs: accessing the most recent value emitted by an observable

As shown in the demo and indicated by the title const { combineLatest, interval, of } = rxjs; const { first, last, sample, take, withLatestFrom } = rxjs.operators; const numbers = interval(1000); const takeFourNumbers = numbers.pipe(take(4)); takeFourNu ...

Modifying the interface state in React with TypeScript is not permitted

I encountered a compilation error in the code below, where I am unable to modify the state in closeLeftCol function. The error message states: Cannot assign to leftWidth because it is a constant or read only property: interface ILayoutState{ r ...

Aggregating and organizing all TypeScript files within the project while preserving the file hierarchy

Looking to utilize a task runner such as Grunt or Gulp to compile TS to JS files in various locations within the project folder. The goal is to ensure that the outputted JS files are placed in the same directory where the project will look for them alongsi ...

Invoke a component's function in a different component

Upon clicking the button, I am trying to execute the 'exportHistoryToCSV' method within this component, which in turn calls a method from another component. However, I am encountering an error. @UntilDestroy() @Component({ selector: 'd ...

Issue with ReactJS Typescript: Cannot assign type 'number' to type '0, 8, 16, 24, 32, 40, or undefined'

I am looking to implement a grid from material-ui in react using typescript. You can view the live demo here. I have made adjustments to the example to make it work with typescript. Here is how my demo.jsx file looks like: import { withStyles } from &apo ...

The Tools of the Trade: TypeScript Tooling

Trying out the amazing Breeze Typescript Entity Generator tool but encountering an error consistently. Error: Experiencing difficulty in locating the default implementation of the 'modelLibrary' interface. Options include 'ko', 'b ...

When an email link is clicked in Angular, Internet Explorer is automatically logged out and needs to be refreshed

I'm currently working on a project using an Angular 4 Application. One of the elements in my HTML code is an href link that has a mailto: email address. The issue I'm facing is that when I click on this link while using IE11, either I get autom ...

The perplexing actions of Map<string, string[]> = new Map() have left many scratching their heads

I encountered an issue while trying to add a value to a map in my Angular project. The map is initially set up using the following code: filters: Map<string, string[]> = new Map(); However, when I attempt to add a value to this map, it starts displa ...

Steps for utilizing a function from the parent component to initialize TinyMCE

I have implemented an uploading function in my parent component. As I set up tinymce, I connected the [init] property of my component to the loadConfig() function. <editor [(ngModel)]="data" [init]="loadConfig()"></editor> The loadConfig func ...

Leverage a single attribute from a Typescript interface within another interface

Let's imagine we have a TypeScript Interface like this export interface IMyObj { id: string; type: 'AA' | 'AZ' | 'XY'; ... } Now, I require another interface that includes the same type field export interfa ...