Typescript:来自枚举的字符串文字联合类型

AKG*_*AKG 15 enums typescript

我想从枚举中得到一个字符串文字联合.

对于这个枚举......

enum Weekday {
    MONDAY = 'mon',
    TUESDAY = 'tue',
    WEDNESDAY = 'wed'
}
Run Code Online (Sandbox Code Playgroud)

......我想得到这个:

type WeekdayType = 'mon' | 'tue' | 'wed';
Run Code Online (Sandbox Code Playgroud)

我试过typeof keyof Weekday但结果却是'MONDAY' | 'TUESDAY' | 'WEDNESDAY'.感觉解决方案可能与映射类型有关,但我似乎无法绕过它.

我该怎么做呢?

des*_*ise 32

打字稿 4.1+:

如前所述,这可以通过使用模板文字类型来实现,如下所示:

type WeekdayType = `${Weekday}`;
Run Code Online (Sandbox Code Playgroud)

打字稿 3.4+:

跟进@jcalz 的回答和@just-boris 的评论,这是一个带有 const 断言的示例:

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

type Weekday = (typeof Weekday)[keyof typeof Weekday];
Run Code Online (Sandbox Code Playgroud)

编辑:

为那些想要深入挖掘的人写了一篇博文


jca*_*alz 16

这不能编程方式...你想转换的类型Weekday,也就是Weekday.MONDAY | Weekday.TUESDAY | Weekday.WEDNESDAY,在类型WeekdayType"mon" | "tue" | "wed".此转换是一种扩展形式,因为它Weekday是以下子类型WeekdayType:

type WeekdayExtendsWeekdayType = 
  Weekday extends WeekdayType ? true : false
// type WeekdayExtendsWeekdayType = true
Run Code Online (Sandbox Code Playgroud)

不幸的是,编译器没有给你一个从枚举类型中删除"枚举"的句柄,并留下普通的文字类型.


那么,解决方法?也许你实际上并不需要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],
Run Code Online (Sandbox Code Playgroud)

如果你检查它的命名Weekday的行为就像一个枚举对象:

console.log(Weekday.TUESDAY); // tue
Run Code Online (Sandbox Code Playgroud)

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

const w: Weekday = "wed"; // okay
const x: Weekday = "xed"; // error
Run Code Online (Sandbox Code Playgroud)

因此,在此变通方法中,没有"枚举"性,因此无需区分类型Weekday和类型WeekdayType.它与实际enum(包括类似的类型Weekday.MONDAY,您必须表示为繁琐typeof Weekday.MONDAY或为其创建不同的类型别名)略有不同,但它可能表现得足够相似而且非常有用.那对你有用吗?

希望有所帮助.祝好运!

  • 更新:从 typescript 3.4 开始,不再需要特殊的 `lit` 函数。您可以使用 [const 断言](https://devblogs.microsoft.com/typescript/announcing-typescript-3-4/#const-assertions) 代替 (7认同)
  • ```type WeekdayType = `${Weekday}`;``` 很邪恶 (2认同)

coy*_*508 15

使用Typescript 4.1可以做到!

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

type WeekdayType = `${Weekday}`;
Run Code Online (Sandbox Code Playgroud)

警告:这仅适用于字符串枚举值,不适用于数字枚举值。

  • 有人可以提供此行为的文档吗?! (4认同)
  • 一个更简单的方法是:输入 WeekdayUnion = `${Weekday}`; 就是这样! (2认同)
  • @MichaelG是的,您只需在开发依赖项中的项目 package.json 中将 typescript 版本更新为 4.1 (2认同)