grpc / grpc/grpc-web

Incorrect TS type definition for protobuf enums

Open
#963 1 comment 13 reactions 0 assignees View on GitHub
typescript
Dominant language
JavaScript
Stars
9.3k
Forks
802
Avg merge
1d 7h
Merged PRs (30d)
5

Description

[Protobuf `enum`s](https://developers.google.com/protocol-buffers/docs/proto3#enum) are incorrectly types as [TypeScript `enum`s](https://www.typescriptlang.org/docs/handbook/enums.html). This is incorrect because TS enums map from item name to value __and__ from value to item name.

### Example

Proto file:

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

Generated JS:

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

TypeScript definition (`.d.ts`)

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

However, the type definition actually means [this](https://www.typescriptlang.org/play?#code/KYDwDg9gTgLgBMAdgVwLZwCoEMDmcDeAUHCXAOoDyASgCJwC8cADADTGmW0D6AYtVwEUAsgEEqAaQZwAjG1LlqNXvwDKGMVIBMbAL5A):

```js
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:

```js
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 `message`s):

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

I also want to point out that [`const enum`](https://www.typescriptlang.org/docs/handbook/enums.html#const-enums)s are not the solution since TS will insert the values of `const enum`s at compile time. `const enum`s are meant for purely internal usage only and not for APIs.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.