Given the enum
enum E {
A = "apple",
B = "banana",
C = "cherries"
}
your original version didn't work primarily because you were indexing into the E
type, which is not the same as the E
value (whose type is typeof E
and not E
). See Generic type to get enum keys as union string in typescript? and its answer for more information about this.
The type you're looking for is very close to just E
. Both E
and "apples" | "banana" | "cherries"
are the union of literal types of the enum values. But E
treated as a special subtype of the literal type, specifically so you can't just write, say, "cherries"
in place of E.C
.
In some sense, the whole point of an enum
is to abstract away the actual literal types of the values. If you actually care about these literal types, you might want to avoid enum
entirely in favor of an object of the same shape:
const EObject = {
A: "apple",
B: "banana",
c: "cherries"
} as const;
type EKey = keyof typeof EObject;
// type EKey = "A" | "B" | "c"
type EValue = (typeof EObject)[EKey];
// type EValue = "apple" | "banana" | "cherries"
That as const
asks the compiler to keep track of the string literal types of the object values, so you can extract both the keys and the value types easily.
But maybe your use case doesn't allow this.
If you really want to extract "apple" | "banana" | "cherries"
from E
, you can use template literal types to ask "what happens when I serialize E
as a string
"?
enum E {
A = "apple",
B = "banana",
C = "cherries"
}
type EValue = `${E}`;
// type EValue = "apple" | "banana" | "cherries"
That produces the desired union. Note that if E
were a numeric enum or a mixed enum, you'd end up with a string version of the numbers.
enum F {
D = "durian",
E = 123,
F = "figs",
G = 456
}
type FValueOops = `${F}`
// type FValueOops = "durian" | "figs" | "123" | "456"
If such things matter you could more effort teasing numeric and string literals out:
type EnumToLiteral<T extends string | number> =
T extends string ? `${T}` : `${T}` extends `${infer N extends number}` ? N : never;
type FValue = EnumToLiteral<F>;
// type FValue = "durian" | 123 | "figs" | 456
But I'd advise pursuing an as const
object instead of an enum
before doing this sort of type juggling.
Playground link to code