Typescript: string literal union type from enum

时间:2018-09-18 19:55:59

标签: typescript enums

I'd like to get a string literal union from an enum.

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?

3 个答案:

答案 0 :(得分:12)

这无法通过编程方式完成...您正在尝试将Weekday类型Weekday.MONDAY | Weekday.TUESDAY | Weekday.WEDNESDAY转换为WeekdayType类型"mon" | "tue" | "wed" 。由于WeekdayWeekdayType的子类型,因此此转换是扩大的一种形式:

type WeekdayExtendsWeekdayType = 
  Weekday extends WeekdayType ? true : false
// type WeekdayExtendsWeekdayType = true

不幸的是,编译器没有给您提供从枚举类型中删除“枚举”性质并使您拥有普通文字类型的句柄。


那么,解决方法?也许您实际上并不需要enum,但可以处理其属性值为字符串文字的对象:

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],

如果进行检查,则名为Weekday value 的行为类似于枚举对象:

console.log(Weekday.TUESDAY); // tue

名为Weekday type 的行为类似于您调用"mon" | "tue" | "wed"的字符串值WeekdayType的并集:

const w: Weekday = "wed"; // okay
const x: Weekday = "xed"; // error

因此,在此替代方法中,没有“枚举”性质,因此无需将类型Weekday与类型WeekdayType区分开。与实际的enum(包括Weekday.MONDAY之类的类型,您必须将其表示为笨重的typeof Weekday.MONDAY或创建其他类型)有所不同别名),但它的行为可能也足够有用。这样对您有用吗?

希望有帮助。祝你好运!

答案 1 :(得分:3)

使用Typescript 4.1,可以做到!

enum Weekday {
  MONDAY = 'mon',
  TUESDAY = 'tue',
  WEDNESDAY = 'wed'
}

type WeekdayType = `${Weekday}`;

注意:仅适用于字符串枚举值,不适用于数字枚举值。

答案 2 :(得分:0)

紧接着@jcalz答案和@ just-boris的评论,下面是一个带有const断言(打字稿3.4+)的示例:

const Weekday = {
  MONDAY: "mon",
  TUESDAY: "tue",
  WEDNESDAY: "wed",
} as const;

type Weekday = (typeof Weekday)[keyof typeof Weekday],