简体   繁体   English

如何将 Typescript 类型转换为枚举?

[英]How to convert a Typescript type to an enum?

I want to convert a custom Typescript type into an enum.我想将自定义 Typescript 类型转换为枚举。 Here is my type:这是我的类型:

export type TradeRequest {
  status: 'trade',
  id: ItemId,
  slotNumber: number,
}

ItemId itself is an enum. ItemId本身是一个枚举。 This is what it looks like:这是它的样子:

export enum ItemId {
  SHOVEL = 10000,
  SWORD = 10001,
  APPLE = 20000,
}

Here is the enum that I'm trying to create:这是我要创建的枚举:

export enum TradeRequest {
  STATUS = 'item',
  ITEM_ID = ItemId,
  SLOT_NUMBER = number,
}

When I do this, I get this error:当我这样做时,我收到此错误:

Only numeric enums can have computed members, but this expression has 'typeof ItemId' If you do not need exhaustiveness checks, consider using an object literal instead.

You cannot compose enums with other enums.您不能将枚举与其他枚举组合在一起。 TypeScript enums are untagged. TypeScript 枚举未标记。 Therefore, they are simply values without context that you access by accessing the members with dot notation.因此,它们只是没有上下文的值,您可以通过使用点表示法访问成员来访问这些值。 You could try using a regular union like this:您可以尝试使用这样的常规联合:

export enum ItemId {
  SHOVEL = 10000,
  SWORD = 10001,
  APPLE = 20000,
}

type TradeRequest = "item" | ItemId | number;

However, ItemId 's type is simply a union of the possible values - 10000 | 10001 | 20000但是, ItemId的类型只是可能值的联合 - 10000 | 10001 | 20000 10000 | 10001 | 20000 10000 | 10001 | 20000 . 10000 | 10001 | 20000 Therefore, the number type will eagerly consume it thus making the type compute to "item" | number因此, number类型将急切地使用它,从而使类型计算为"item" | number "item" | number . "item" | number I advise you use a C-Style union as I have described creating in this answer .我建议您使用 C-Style 联合,正如我在这个答案中描述的那样。 Basically, you have a type object that looks like an enum but it's just an object and you create it via object literals and it forces you to only allow one member.基本上,你有一个类型 object 看起来像一个枚举,但它只是一个 object 并且你通过 object 文字创建它并且它强制你只允许一个成员。 This allows us to tag your data so that the ItemId type is not consumed by number type:这允许我们标记您的数据,以便ItemId类型不被number类型消耗:

export enum ItemId {
  SHOVEL = 10000,
  SWORD = 10001,
  APPLE = 20000,
}

// from https://stackoverflow.com/a/71476167/10873797
type CUnion<T extends Record<PropertyKey, unknown>>
  = { [K in keyof T]: { [_ in K]: T[K] } & { [_ in Exclude<keyof T, K>]?: undefined } }[keyof T];

type TradeRequest = CUnion<{
  status: 'trade',
  id: ItemId,
  slotNumber: number,
}>;

const foo1: TradeRequest = {
    id: ItemId.APPLE
};

const foo2: TradeRequest = {
    slotNumber: 2354,
};

const foo3: TradeRequest = {
    status: "trade"
};

// then you access it like this

if (foo1.id !== undefined) {
    // you know that it is the id variant
    foo1.id // ItemId
    foo1.slotNumber // undefined
    foo1.status // undefined
}

TypeScript Playground Link TypeScript 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM