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

Typesafe API to retrieve enums from strings #642

Open
dimo414 opened this issue Apr 2, 2024 · 4 comments
Open

Typesafe API to retrieve enums from strings #642

dimo414 opened this issue Apr 2, 2024 · 4 comments

Comments

@dimo414
Copy link
Contributor

dimo414 commented Apr 2, 2024

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.

@jcready
Copy link
Contributor

jcready commented Apr 3, 2024

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;
}

@dimo414
Copy link
Contributor Author

dimo414 commented Apr 3, 2024

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.

@jcready
Copy link
Contributor

jcready commented Apr 3, 2024

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

@dimo414
Copy link
Contributor Author

dimo414 commented Apr 4, 2024

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.

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