protobuf-ts icon indicating copy to clipboard operation
protobuf-ts copied to clipboard

Typesafe API to retrieve enums from strings

Open dimo414 opened this issue 1 year ago • 4 comments

To my knowledge, TypeScript's support for going from a string to an enum requires that the string be typed as keyof typeof MyEnum. This works for string literals like the example but doesn't work for arbitrary strings which could be invalid values. Here's a playground demo which reports an Element implicitly has an 'any' type error.

As a more concrete example, I am receiving a string from an untyped client that "should" be an enum value. To satisfy the type checker I need to cast the key as the expected type, and then handle the potential undefined that is returned on a miss to convert it to the enum's 0th value:

let key = "MAYBE";
// notice the type here is "wrong" because the index lookup returns undefined,
// but I don't want to pollute myEnum with |undefined, I want it to use the default
let myEnum: MyEnum = MyEnum[key as keyof typeof MyEnum];
if (myEnum === undefined) {
  myEnum = MyEnum.ANY;
}

It would be really useful if protobuf-ts provided a more ergonomic string-to-enum utility than what TypeScript provides. At a minimum it should support arbitrary strings without needing casting, and potentially it could behave like the protobuf spec and return the 0th enum value rather than undefined.

dimo414 avatar Apr 02 '24 22:04 dimo414

You should be able to create these functions yourself (playground):

function isKeyof<T extends {}>(t: T, key: string): key is string & keyof T {
    return key in t;
}

function getEnumValueOrDefault<T extends {}>(e: T, key: string): 0 | T[string & keyof T] {
    return isKeyof(e, key) ? e[key] : 0;
}

jcready avatar Apr 03 '24 15:04 jcready

Yeah I agree it's possible to workaround, but I was hoping protobuf-ts could include these e.g. in the generated code of each enum so it's right on the type, rather than something we need to pull together or go find.

dimo414 avatar Apr 03 '24 22:04 dimo414

The enums are just TS enums. No extra properties or methods can be added and have them be TS enums.

jcready avatar Apr 03 '24 22:04 jcready

Fair enough; well IMO there's room for protobuf-ts to improve the ergonomics of string->enum lookups vs. what TypeScript provides out of the box, but I understand if you disagree.

dimo414 avatar Apr 04 '24 02:04 dimo414