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

qybjjes1  于 2022-11-30  发布在  TypeScript
关注(0)|答案(3)|浏览(150)

我想从枚举中得到一个字符串联合。
对于此枚举...

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

...我想得到这个:

type WeekdayType = 'mon' | 'tue' | 'wed';

我尝试了typeof keyof Weekday,但结果是'MONDAY' | 'TUESDAY' | 'WEDNESDAY'。感觉解决方案可能与Map类型有关,但我似乎无法理解它。
我该怎么做?

fbcarpbf

fbcarpbf1#

请参阅TS4.1 ANSWER

type WeekdayType = `${Weekday}`;

TS-4.1之前的回答:
这不能通过编程来完成......您正在尝试将Weekday类型(即Weekday.MONDAY | Weekday.TUESDAY | Weekday.WEDNESDAY)转换为WeekdayType类型(即"mon" | "tue" | "wed")。这种转换是 * welling * 的一种形式,因为WeekdayWeekdayType的子类型:

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

不幸的是,编译器没有提供句柄来从枚举类型中删除“enum”属性,而留给您的是纯文本类型。
那么,解决方法是什么呢?也许您实际上并不需要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],

如果检查它,名为Weekdayvalue 的行为就像一个枚举对象:

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

而名为Weekdaytype 的行为类似于字符串值"mon" | "tue" | "wed"的并集,您正在调用WeekdayType

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

因此,在此解决方案中,没有“枚举”,因此不需要区分Weekday类型和WeekdayType类型。(其中包括Weekday.MONDAY等 * 类型 *,您必须将其表示为繁琐的typeof Weekday.MONDAY或为其创建不同的类型别名),但它的行为可能很相似,这对你有用吗?
希望对你有帮助,祝你好运!

rkue9o1l

rkue9o1l2#

键入脚本4.1+:

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

type WeekdayType = `${Weekday}`;

键入脚本3.4+:

在@jcalz的回答和@just-boris的评论之后,下面是一个使用constAssert的例子:

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

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

编辑:

为那些想深入挖掘的人写了一个blog post

8i9zcol2

8i9zcol23#

有了Typescript 4.1,这一切都可以做到!

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

type WeekdayType = `${Weekday}`;

对于数字枚举,感谢@okku:

enum ThreeDigits {
  ZERO = 0,
  ONE = 1,
  TWO = 2
}

type ThreeDigitsType = `${ThreeDigits}` extends `${infer T extends number}` ? T : never;

相关问题