-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Indexed access lookup on enum type could produce specific key types #50933
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
Comments
|
Same goes if you try type EnumKey = keyof typeof Enum // "A"
type EnumValWrong = Enum[EnumKey] // Property "A" does not exist on type "Number"
type EnumVal = typeof Enum[EnumKey] // Enum.A Thus, you need the // type T = Enum[Enum.A];
type T = typeof Enum[Enum.A]; But as I said above, this evaluates to |
Isn’t this a duplicate of #38806? |
Potentially. I read that post as more of an issue reporting that what you would expect to work did not work for that specific case. I opened this to offer a more general suggestion for the problem rather than report an issue since the problem mentioned in #38806 can be solved with the workaround I mentioned above. My apologies if this is a duplicate--this is my first issue on the repo. I did find #38806 before I posted this and linked this thread afterward as a solution to their problem. |
You're basically asking for a type alias to do a thing you can already today in userland, which isn't something we do. |
A simpler form is type KeyHelper<E, K extends keyof E, V> = K extends unknown ? E[K] extends V ? K : never : never;
type KeyName<E, V> = KeyHelper<E, keyof E, V>;
type TheKeyName = KeyName<typeof Enum, Enum.B>; |
Thank you for providing a simpler form of the type alias. I appreciate the thought that went into your reply. Maybe you can help me better understand my underlying confusion.
Okay, that makes sense. However, I feel like const nameOfA = Enum[Enum.A]; // evaluates to "A"
type T = typeof Enum[Enum.A]; // evaluates to string It's entirely possible (probably likely) that this functionality is intended and there is something that I am missing. I would be interested to hear your thoughts on the advantages of the current implementation. |
No reason it couldn't be the more-specific type |
@RyanCavanaugh I kind of get the impression this issue counts as that proposal (and you tagged it
|
Well, fair 😅 |
Hey there, trying to have this issue on the backlog by adding my use case: enum E {
First,
Second
}
function getName(x: E) {
return E[x]
}
let x = getName(E.First) satisfies keyof typeof E
// ^? string The exact use case is retrieving names from protobuf enums, which are implemented as numeric enums: /** @generated */
export enum Something {
/** @generated */
UNSPECIFIED = 0,
/** @generated */
INTERNAL = 1,
// ...
} We send integers over the wire, but return strings in APIs. We would like that Edit: and we also use |
Add a reversal typeenum Enum {
A,
B,
}
type ToNumber<S> = S extends `${infer N extends number}` ? N : S;
type EnumKey = keyof typeof Enum; // "A" | "B"
type EnumVal = ToNumber<`${Enum}`>; // 0 | 1
type EnumForward = {
[key in EnumKey]: (typeof Enum)[key];
}; // { A: Enum.A; B: Enum.B; }
type EnumReverse = {
[key in EnumKey as (typeof Enum)[key]]: key;
}; // { 0: "A"; 1: "B"; }
type EnumAKey = EnumReverse[Enum.A]; // "A" |
Suggestion
Per the documentation, it is possible to reverse map an enum at runtime:
However, suppose we wanted to get the type of the enum name from the enum value at compile time. That is, get some
type T = "A"
fromEnum.A
. From the example above, we would expect something like the following to work:As written above, the compiler fails to get the correct type. However, I have found a workaround:
It would be nice if this could be abstracted away from the developer.
The text was updated successfully, but these errors were encountered: