将描述属性添加到枚举并在TypeScript中阅读此描述

Gol*_*Age 9 enums typescript ecmascript-6

我想知道如何在TypeScript中向枚举添加描述属性。我想创建如下的枚举(或类似的东西):

public enum Sample
{
    [Display(Name = "Blah V")]
    V,

    [Display(Name = " Blah IV")]
    IV,

    [Display(Name = " Blah III")]
    III,
}
Run Code Online (Sandbox Code Playgroud)

为了能够对此类枚举执行基本操作,我将创建通用的EnumHelper。该帮助器类应包含允许使用的方法:获取描述值,获取名称和数字值。问题是如何在打字稿中实现这一点?如果无法向枚举添加属性,有什么办法吗?我希望能够:

-  get number of enum value,
-  get description value,
-  get the name of enum field.
Run Code Online (Sandbox Code Playgroud)

例如对于Sample.IV它将是:

1, 
Blah IV, 
IV.
Run Code Online (Sandbox Code Playgroud)

man*_*h_s 18

下面的方法将是类型安全的(自动完成工作)并且它使用普通对象。它基于TypeScript 的这一特性

export enum Sample {
  I = 1,
  II = 2,
  III = 3
}

export const SampleLabel: { [key in Sample]: string } = {
  [Sample.I]: "ONE",
  [Sample.II]: "TWO",
  [Sample.III]: "THREE",
};
Run Code Online (Sandbox Code Playgroud)

  • @DanKing 是的,如果你错过了一个钥匙,它确实会给你一个错误。 (2认同)

man*_*nza 17

在此处建立的另一个有趣的解决方案是使用ES6 Map:

export enum Sample {
  V,
  IV,
  III
}

export const SampleLabel = new Map<number, string>([
  [Sample.V, 'FIVE'],
  [Sample.IV, 'FOUR'],
  [Sample.III, 'THREE']
]);
Run Code Online (Sandbox Code Playgroud)

使用

console.log(SampleLabel.get(Sample.IV)); // FOUR
Run Code Online (Sandbox Code Playgroud)


小智 7

已接受答案的变体。替换number为您的enum类型以提高类型安全性。

 export enum Sample {
      V,
      IV,
      III
    }

export const SampleLabel = new Map<Sample, string>([
  [Sample.V, 'FIVE'],
  [Sample.IV, 'FOUR'],
  [Sample.III, 'THREE']
]);
Run Code Online (Sandbox Code Playgroud)


jca*_*alz 5

TypeScript 不允许您向enum元素添加属性,它在运行时只是一个原始字符串或数字。相反,你必须做一些事情,比如创建一个新类型,它保存对这些元素的引用,并且还拥有你想要的方法或属性。

这是一种可能的方法。enum像这样从你的平原开始:

enum SampleEnum {
  V, IV, III
}
Run Code Online (Sandbox Code Playgroud)

让我们为您的扩展类型提供一个接口定义。它有一个name、一个description和一个number。请注意,此类型是通用的,因此我们可以很快缩小namenumber类型的范围:

interface ISample<N extends number, S extends string> {
  readonly name: S;
  readonly description: string;
  readonly number: N;
}
Run Code Online (Sandbox Code Playgroud)

这是一个函数,它可以获取您的SampleEnum对象并返回具有相同键但具有实现扩展接口的值的内容:

function makeSample<E extends Record<Extract<keyof E, string>, number>>(
  mapping: E
): { [K in Extract<keyof E, string>]: ISample<E[K], K> } {
  const ret = {} as { [K in Extract<keyof E, string>]: ISample<E[K], K> };
  (Object.keys(mapping).filter(k => k !== (+k) + "") as
    (Extract<keyof E, string>)[]
  ).forEach(k => {
    ret[k] = {
      name: k,
      description: "Blah " + k,
      number: mapping[k]
    }
  });
  return ret;
}
Run Code Online (Sandbox Code Playgroud)

这可能是很多类型的杂耍,但它基本上只是从中提取字符串值键SampleEnum(并忽略在运行时将数字键添加到数字枚举的反向映射)并为每个扩展接口构建一个实例,在一个有点类型安全的方式。

最后,让我们创建Sample代表我们的值和类型enum

const Sample = makeSample(SampleEnum);
type Sample = (typeof Sample)[keyof typeof Sample]
Run Code Online (Sandbox Code Playgroud)

好的,让我们使用它:

const nameOfIV = Sample.IV.name; // "IV"
console.log(nameOfIV); // "IV"
const numberOfIII = Sample.III.number; // SampleEnum.III
console.log(numberOfIII); // 1
const descriptionOfV = Sample.V.description; // string
console.log(descriptionOfV); // "Blah V"

const goodSample: Sample = Sample.III; // okay
const badSample: Sample = {
  name: "II", 
  description: "oops", 
  number: 3
}; // error, name doesn't match
Run Code Online (Sandbox Code Playgroud)

对我来说看起来很合理。 自己看看。当然,还有其他方法可以解决它,但这应该会给你一个想法。希望有帮助。祝你好运!


Son*_*oul 5

这种模式对我有用:

export enum PriceTypes {
    Undefined = 0,
    UndefinedDescription = 'Undefined' as any,
    UserEntered = 1,
    UserEnteredDescription = 'User Entered' as any,
    GeneratedFromTrade = 2,
    GeneratedFromTradeDescription = 'Generated From Trade' as any,
    GeneratedFromFreeze = 3,
    GeneratedFromFreezeDescription = 'Generated Rom Freeze' as any
}
Run Code Online (Sandbox Code Playgroud)

...

    GetDescription(e: any, id: number): string {
        return e[e[id].toString() + "Description"];
    }
    getPriceTypeDescription(price: IPricePoint): string {
        return this.GetDescription(PriceTypes, price.priceType);
    }
Run Code Online (Sandbox Code Playgroud)

  • 枚举的错误使用。UndefinedDescription 不是有效的 PriceType。 (6认同)