patterntypescriptCritical
Typescript: string literal union type from enum
Viewed 0 times
typescriptliteralenumfromunionstringtype
Problem
I'd like to get a string literal union from an enum.
For this enum…
… I'd like to get this:
I tried
How do I do this?
For this enum…
enum Weekday {
MONDAY = 'mon',
TUESDAY = 'tue',
WEDNESDAY = 'wed'
}… I'd like to get this:
type WeekdayType = 'mon' | 'tue' | 'wed';I tried
typeof keyof Weekday but that resulted in 'MONDAY' | 'TUESDAY' | 'WEDNESDAY'. Feel like the solution might have to do with mapped types but I can't seem to wrap my head around it.How do I do this?
Solution
See TS4.1 ANSWER:
PRE TS-4.1 ANSWER:
This can't be done programmatically... you're trying to convert the type
Unfortunately the compiler doesn't give you a handle to remove an "enum"-ness from the enum type and leave you with plain literal types.
So, workarounds? Maybe you don't actually need an
If you inspect it, the value named
while the type named
So in this workaround, there is no "enum"-ness, and therefore no need to distinguish the type
type WeekdayType = `${Weekday}`;PRE TS-4.1 ANSWER:
This can't be done programmatically... you're trying to convert the type
Weekday, which is Weekday.MONDAY | Weekday.TUESDAY | Weekday.WEDNESDAY, to the type WeekdayType which is "mon" | "tue" | "wed". This conversion is a form of widening, since Weekday is a subtype of WeekdayType:type WeekdayExtendsWeekdayType =
Weekday extends WeekdayType ? true : false
// type WeekdayExtendsWeekdayType = trueUnfortunately the compiler doesn't give you a handle to remove an "enum"-ness from the enum type and leave you with plain literal types.
So, workarounds? Maybe you don't actually need an
enum, but can make do with an object whose property values are string literals:const lit = (v: V) => v;
const Weekday = {
MONDAY: lit("mon"),
TUESDAY: lit("tue"),
WEDNESDAY: lit("wed")
}
type Weekday = (typeof Weekday)[keyof typeof Weekday],If you inspect it, the value named
Weekday behaves like an enum object:console.log(Weekday.TUESDAY); // tuewhile the type named
Weekday behaves like the union of string values "mon" | "tue" | "wed" that you were calling WeekdayType:const w: Weekday = "wed"; // okay
const x: Weekday = "xed"; // errorSo in this workaround, there is no "enum"-ness, and therefore no need to distinguish the type
Weekday from the type WeekdayType. It's a little different from an actual enum (which includes types like Weekday.MONDAY, which you'd have to represent as the cumbersome typeof Weekday.MONDAY or create a different type alias for it), but it might behave similarly enough to be useful. Does that work for you?Code Snippets
type WeekdayType = `${Weekday}`;type WeekdayExtendsWeekdayType =
Weekday extends WeekdayType ? true : false
// type WeekdayExtendsWeekdayType = trueconst lit = <V extends keyof any>(v: V) => v;
const Weekday = {
MONDAY: lit("mon"),
TUESDAY: lit("tue"),
WEDNESDAY: lit("wed")
}
type Weekday = (typeof Weekday)[keyof typeof Weekday],console.log(Weekday.TUESDAY); // tueconst w: Weekday = "wed"; // okay
const x: Weekday = "xed"; // errorContext
Stack Overflow Q#52393730, score: 243
Revisions (0)
No revisions yet.