1

Let's imagine I have 2 Nest.js services: Service A and Service B, which communicate using gRPC. I am trying to pass an object of type UserSettings from Service A to Service B via Remote Procedure Call (RPC)

Let's imagine in service A we have types:

enum Language {
  AMERICAN_ENGLISH = "en/us",
  BRITISH_ENGLISH = "en/uk",
  ITALIAN = "it"
}

type UserSettings = {
  theme: "dark" | "white";
  language: Language;
  device: string | number;
}

How to correctly map UserSettings with this rich Typescript type to .proto file?

I have reached the point where I understand I can not use as many features in protobufs as I can in Typescript.

So, should I use some mapper functions, to map UserSettings to UserSettingsProto before calling rpc in Service A, and then in Service B, to map from UserSettingsProto to UserSettings, or is there a better approach?

1 Answers1

0

You should always map Protocol Buffer generated types to application types even when this appears to be "perfect".

One tenet of Protobufs that's worth remembering when using a single language, is that the mechanism permits RPCs between code from multiple languages. It's possible to represent any (!?) language-specific type using Protobuf's types (even though sometimes it may seem contorted to do so).

This not only provides a degree-of-freedom from the potential for changes in the stubs and avoids nuances in the stub types but it permits the addition of (see below) e.g. toString functions for mapping enums to strings.

You can map enum:

enum Language {
  AMERICAN_ENGLISH = 0; // 0 must be used and it is the default value
  BRITISH_ENGLISH = 1;
  ITALIAN = 2;
  ...
}

NOTE TypeScript's support for string(-mapped) enums would need to be manifest as some toString type function in your code.

message UserSettings {
  bool theme = 1;            // Or another enum
  Language language = 2;
  oneof device {             // See NOTE below
    string foo = 1;
    uint32 bar = 2;
}

NOTE oneof permits union types like your device but the implementation differs by langauge. Generally (except Go!?) the name of the oneof type (here device) doesn't manifest in the stub. Either way, Protobufs requires that each possible type be named i.e. device when it's a string (here foo) and device when it's a number (here uint32 and bar).

DazWilkin
  • 32,823
  • 5
  • 47
  • 88