以下代码可用于在TypeScript中创建enum:

enum e {
    hello = 1,
    world = 2
};

这些值可以通过以下方式访问:

e.hello;
e.world;

我如何创建一个字符串值enum ?

enum e {
    hello = "hello", // error: cannot convert string to e
    world = "world"  // error 
};

当前回答

我只是声明了一个接口,并使用该类型的变量访问枚举。保持接口和枚举同步实际上很容易,因为如果枚举中有什么变化,TypeScript会报错,就像这样。

typeof EAbFlagEnum类型的参数不可赋值 参数类型为“IAbFlagEnum”。属性“Move”类型缺失 “typeof EAbFlagEnum”。

这种方法的优点是在各种情况下使用enum(接口)不需要类型强制转换,因此支持更多类型的情况,例如switch/case。

// Declare a TypeScript enum using unique string 
//  (per hack mentioned by zjc0816)

enum EAbFlagEnum {
  None      = <any> "none",
  Select    = <any> "sel",
  Move      = <any> "mov",
  Edit      = <any> "edit",
  Sort      = <any> "sort",
  Clone     = <any> "clone"
}

// Create an interface that shadows the enum
//   and asserts that members are a type of any

interface IAbFlagEnum {
    None:   any;
    Select: any;
    Move:   any;
    Edit:   any;
    Sort:   any;
    Clone:  any;
}

// Export a variable of type interface that points to the enum

export var AbFlagEnum: IAbFlagEnum = EAbFlagEnum;

使用变量,而不是枚举,可以产生所需的结果。

var strVal: string = AbFlagEnum.Edit;

switch (strVal) {
  case AbFlagEnum.Edit:
    break;
  case AbFlagEnum.Move:
    break;
  case AbFlagEnum.Clone
}

标记是我的另一个需要,所以我创建了一个NPM模块,添加到这个例子中,并包括测试。

https://github.com/djabraham/ts-enum-tools

其他回答

TypeScript < 2.4

/** Utility function to create a K:V from a list of strings */
function strEnum<T extends string>(o: Array<T>): {[K in T]: K} {
  return o.reduce((res, key) => {
    res[key] = key;
    return res;
  }, Object.create(null));
}

/**
  * Sample create a string enum
  */

/** Create a K:V */
const Direction = strEnum([
  'North',
  'South',
  'East',
  'West'
])
/** Create a Type */
type Direction = keyof typeof Direction;

/** 
  * Sample using a string enum
  */
let sample: Direction;

sample = Direction.North; // Okay
sample = 'North'; // Okay
sample = 'AnythingElse'; // ERROR!

从https://basarat.gitbooks.io/typescript/docs/types/literal-types.html

到源代码链接,你可以找到更多更简单的方法来实现字符串文字类型

我只是声明了一个接口,并使用该类型的变量访问枚举。保持接口和枚举同步实际上很容易,因为如果枚举中有什么变化,TypeScript会报错,就像这样。

typeof EAbFlagEnum类型的参数不可赋值 参数类型为“IAbFlagEnum”。属性“Move”类型缺失 “typeof EAbFlagEnum”。

这种方法的优点是在各种情况下使用enum(接口)不需要类型强制转换,因此支持更多类型的情况,例如switch/case。

// Declare a TypeScript enum using unique string 
//  (per hack mentioned by zjc0816)

enum EAbFlagEnum {
  None      = <any> "none",
  Select    = <any> "sel",
  Move      = <any> "mov",
  Edit      = <any> "edit",
  Sort      = <any> "sort",
  Clone     = <any> "clone"
}

// Create an interface that shadows the enum
//   and asserts that members are a type of any

interface IAbFlagEnum {
    None:   any;
    Select: any;
    Move:   any;
    Edit:   any;
    Sort:   any;
    Clone:  any;
}

// Export a variable of type interface that points to the enum

export var AbFlagEnum: IAbFlagEnum = EAbFlagEnum;

使用变量,而不是枚举,可以产生所需的结果。

var strVal: string = AbFlagEnum.Edit;

switch (strVal) {
  case AbFlagEnum.Edit:
    break;
  case AbFlagEnum.Move:
    break;
  case AbFlagEnum.Clone
}

标记是我的另一个需要,所以我创建了一个NPM模块,添加到这个例子中,并包括测试。

https://github.com/djabraham/ts-enum-tools

我也有同样的问题,然后想出了一个很好用的函数:

每个条目的键和值都是字符串,并且相同。 每个条目的值都是从键派生出来的。(即。“不要重复你自己”,不像字符串值的常规枚举) TypeScript类型成熟且正确。(防止拼写错误) 还有一种简单的方法可以让TS自动完成您的选项。(如。打字MyEnum。,并立即看到可用的选项) 还有其他一些优点。(见答案底部)

效用函数:

export function createStringEnum<T extends {[key: string]: 1}>(keysObj: T) {
    const optionsObj = {} as {
        [K in keyof T]: keyof T
        // alternative; gives narrower type for MyEnum.XXX
        //[K in keyof T]: K
    };
    const keys = Object.keys(keysObj) as Array<keyof T>;
    const values = keys; // could also check for string value-overrides on keysObj
    for (const key of keys) {
        optionsObj[key] = key;
    }
    return [optionsObj, values] as const;
}

用法:

// if the "Fruit_values" var isn't useful to you, just omit it
export const [Fruit, Fruit_values] = createStringEnum({
    apple: 1,
    pear: 1,
});
export type Fruit = keyof typeof Fruit; // "apple" | "pear"
//export type Fruit = typeof Fruit_values[number]; // alternative

// correct usage (with correct types)
let fruit1 = Fruit.apple; // fruit1 == "apple"
fruit1 = Fruit.pear; // assigning a new fruit also works
let fruit2 = Fruit_values[0]; // fruit2 == "apple"

// incorrect usage (should error)
let fruit3 = Fruit.tire; // errors
let fruit4: Fruit = "mirror"; // errors

现在有人可能会问,这个“基于字符串的enum”比只使用:

type Fruit = "apple" | "pear";

有几个优点:

Auto-complete is a bit nicer (imo). For example, if you type let fruit = Fruit., Typescript will immediately list the exact set of options available. With string literals, you need to define your type explicitly, eg. let fruit: Fruit = , and then press ctrl+space afterward. (and even that results in unrelated autocomplete options being shown below the valid ones) The TSDoc metadata/description for an option is carried over to the MyEnum.XXX fields! This is useful for providing additional information about the different options. For example: You can access the list of options at runtime (eg. Fruit_values, or manually with Object.values(Fruit)). With the type Fruit = ... approach, there is no built-in way to do this, which cuts off a number of use-cases. (for example, I use the runtime values for constructing json-schemas)

最近在使用TypeScript 1.0.1时遇到了这个问题,并以这种方式解决了:

enum IEvents {
        /** A click on a product or product link for one or more products. */
        CLICK,
        /** A view of product details. */
        DETAIL,
        /** Adding one or more products to a shopping cart. */
        ADD,
        /** Remove one or more products from a shopping cart. */
        REMOVE,
        /** Initiating the checkout process for one or more products. */
        CHECKOUT,
        /** Sending the option value for a given checkout step. */
        CHECKOUT_OPTION,
        /** The sale of one or more products. */
        PURCHASE,
        /** The refund of one or more products. */
        REFUND,
        /** A click on an internal promotion. */
        PROMO_CLICK
}

var Events = [
        'click',
        'detail',
        'add',
        'remove',
        'checkout',
        'checkout_option',
        'purchase',
        'refund',
        'promo_click'
];

function stuff(event: IEvents):boolean {
        // event can now be only IEvents constants
        Events[event]; // event is actually a number that matches the index of the array
}
// stuff('click') won't work, it needs to be called using stuff(IEvents.CLICK)

为什么不直接使用本地方式访问枚举的字符串呢?

enum e {
  WHY,
  NOT,
  USE,
  NATIVE
}

e[e.WHY] // this returns string 'WHY'