Typescript: string literal union type from enum
Solution 1:
See TS4.1 ANSWER:
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 = true
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 enum
, but can make do with an object whose property values are string literals:
const 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],
If you inspect it, the value named Weekday
behaves like an enum object:
console.log(Weekday.TUESDAY); // tue
while 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"; // error
So 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?
Hope that helps. Good luck!
Solution 2:
TypeScript 4.1+:
As mentioned, this can be achieved by using Template Literal Types like so:
type WeekdayType = `${Weekday}`;
TypeScript 3.4+:
Following up on @jcalz answer and the comment from @just-boris, here's an example with const assertions:
const Weekday = {
MONDAY: "mon",
TUESDAY: "tue",
WEDNESDAY: "wed",
} as const;
type Weekday = (typeof Weekday)[keyof typeof Weekday];
Edit:
Wrote a blog post for those who would like to dig deeper.
Solution 3:
With Typescript 4.1, it can be done!
enum Weekday {
MONDAY = 'mon',
TUESDAY = 'tue',
WEDNESDAY = 'wed'
}
type WeekdayType = `${Weekday}`;
Caveat: This only works with string enum values, not number enum values.