grpc-web icon indicating copy to clipboard operation
grpc-web copied to clipboard

Incorrect TS type definition for protobuf enums

Open RunDevelopment opened this issue 4 years ago • 1 comments

Protobuf enums are incorrectly types as TypeScript enums. This is incorrect because TS enums map from item name to value and from value to item name.

Example

Proto file:

enum Tag {
  WORD = 0;
  WORD_FOR_QMARK = 1;
  WORD_FOR_STAR = 2;
}

Generated JS:

/**
 * @enum {number}
 */
proto.Tag = {
  WORD: 0,
  WORD_FOR_QMARK: 1,
  WORD_FOR_STAR: 2,
};

TypeScript definition (.d.ts)

export enum Tag {
    WORD = 0,
    WORD_FOR_QMARK = 1,
    WORD_FOR_STAR = 2,
}

However, the type definition actually means this:

export var Tag;
(function (Tag) {
    Tag[Tag["WORD"] = 0] = "WORD";
    Tag[Tag["WORD_FOR_QMARK"] = 1] = "WORD_FOR_QMARK";
    Tag[Tag["WORD_FOR_STAR"] = 2] = "WORD_FOR_STAR";
})(Tag || (Tag = {}));

... which is equivalent to:

export var Tag = {
    "0": "WORD",
    "1": "WORD_FOR_QMARK",
    "2": "WORD_FOR_STAR",
    "WORD": 0,
    "WORD_FOR_QMARK": 1,
    "WORD_FOR_STAR": 2,
};

Possible solution

Use a type for enums (same as for messages):

export type Tag = {
    WORD: 0,
    WORD_FOR_QMARK: 1,
    WORD_FOR_STAR: 2,
}

I also want to point out that const enums are not the solution since TS will insert the values of const enums at compile time. const enums are meant for purely internal usage only and not for APIs.

RunDevelopment avatar Sep 23 '20 10:09 RunDevelopment

To be honest, I like the value/name and name/value mapping of a typescript enum. Instead of limiting the typings to name/value mapping only, I would prefer to patch protoc to extend the Javascript code to support the value/name mapping as well. It should be backward compatible and would fit the typescript enum.

As a workaround for now, I can add the missing mapping at runtime, whenever I need this. It is easily possible because of the type enum in the generated d.ts file that allows this but would be impossible with the switch to the suggested solution that prefers type instead of enum.

renkei avatar Jul 28 '21 01:07 renkei