Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP Enum encoding breaks TypeScript? #34

Open
jackwootton opened this issue Sep 29, 2017 · 3 comments
Open

ESP Enum encoding breaks TypeScript? #34

jackwootton opened this issue Sep 29, 2017 · 3 comments
Assignees

Comments

@jackwootton
Copy link

jackwootton commented Sep 29, 2017

From my own experiments with a local ESP and gRPC backend, it seems proto defined enums such as

syntax = "proto3";
package main;

enum MyType {
   NUMBER = 0;
   STRING = 1;
   BOOLEAN = 2;
}

...are received on the (web) client as enum names (strings) and not enum values:

"NUMBER", "STRING", "BOOLEAN"

I could change my client-side TypeScript enums from:

export enum MyType {
  NUMBER = 0,
  STRING,
  BOOLEAN,
}

to

// tslint:disable:no-any
export enum MyType {
  NUMBER = 'NUMBER' as any,
  STRING = 'STRING' as any,
  BOOLEAN = 'BOOLEAN' as any,
}
// tslint:enable:no-any

This works when receiving an enum from the gRPC backend (via the ESP). However, the same enum cannot then be used when the (web) client makes a request (the numeric value must be used).

This appears to be WIA since in ProtoToJson the message is serialized using SerializeToString

std::string binary = message.SerializeAsString();

I'm unsure why my JavaScript client doesn't balk at this, regardless, the result is, an enum with string values. console.log(myEnumInstance) yields:

["OBJECT", "STRING", "BOOLEAN"]

This means while the underlying type is a string (thanks to ESP), any comparison causes a compilation error:

myEnumInstance.map((t:MyType) => {
   console.log(t, typeof t);
   return t;
});

...yields:

OBJECT string
STRING string
BOOLEAN string

Yet the following causes a compilation error:

// Operator '==' cannot be applied to types 'MyType' and '"OBJECT"'.
console.log(t == 'OBJECT');

So, I'm stuck with string values in my enum that I can't use. Again, IDK how it is the web client's OK with this. Perhaps there's some coercion by the HTTP module in Angular?

@jackwootton
Copy link
Author

jackwootton commented Sep 29, 2017

FWIW, my current workaround is:

    // Will not work. Comment out.
    // myEnumInstance: MyType[];

    // Lose type-safety
    // tslint:disable-next-line:no-any
    myEnumInstance: any[];

    // Iterate over strings, ensuring each 't' is type ':string'
    const mappedTypes = myEnumInstance.map((t:string) => {

      // Look-up name of enum using numeric value and compare against t:string.
      // Return actual enum from mapping function.
      switch(t) {
        case MyType[MyType.OBJECT]:
          return MyType.OBJECT;

        case MyType[MyType.STRING]:
          return MyType.STRING;

        case MyType[MyType.BOOLEAN]:
          return MyType.BOOLEAN;

        default:
          return null;
      }
    });

   // Replace string enums, with real enums.
   myEnumInstance = mappedTypes;

@jackwootton jackwootton changed the title Clarification of Enum encoding? ESP Enum encoding breaks TypeScript? Sep 29, 2017
@lizan
Copy link
Contributor

lizan commented Sep 29, 2017

I need some clarification, are you using Endpoints for gRPC with transcoding?

I assume you are using gRPC backend and transcoding, then the JSON mapping for proto3 is defined in protobuf: https://developers.google.com/protocol-buffers/docs/proto3#json

However, the same enum cannot then be used when the (web) client makes a request (the numeric value must be used).

Do you have an example for this?

@jackwootton
Copy link
Author

I'm using gRPC Endpoints with transcoding provided by the ESP. The mapping you linked is problematic because TypeScript string enums were only introduced in version 2.4.

@angular/angular-cli currently does not support TypeScript versions newer than 2.3.4. It's desirable to keep client-side and server-side enums closely aligned, yet the ESP forces client-side enums to be strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants