326

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

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

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

e.hello;
e.world;

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

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

28 回答 28

490

打字稿 2.4

现在有字符串枚举,所以你的代码可以正常工作:

enum E {
    hello = "hello",
    world = "world"
};

打字稿 1.8

从 TypeScript 1.8 开始,您可以使用字符串文字类型来为命名字符串值(这部分是枚举的用途)提供可靠和安全的体验。

type Options = "hello" | "world";
var foo: Options;
foo = "hello"; // Okay 
foo = "asdf"; // Error!

更多:https ://www.typescriptlang.org/docs/handbook/advanced-types.html#string-literal-types

旧版支持

TypeScript 中的枚举是基于数字的。

您可以使用具有静态成员的类:

class E
{
    static hello = "hello";
    static world = "world"; 
}

你也可以简单地说:

var E = {
    hello: "hello",
    world: "world"
}

更新: 基于能够执行var test:E = E.hello;以下操作的要求满足此要求:

class E
{
    // boilerplate 
    constructor(public value:string){    
    }

    toString(){
        return this.value;
    }

    // values 
    static hello = new E("hello");
    static world = new E("world");
}

// Sample usage: 
var first:E = E.hello;
var second:E = E.world;
var third:E = E.hello;

console.log("First value is: "+ first);
console.log(first===third); 
于 2013-03-19T05:04:09.130 回答
117

在 TypeScript 的最新版本 (1.0RC) 中,您可以像这样使用枚举:

enum States {
    New,
    Active,
    Disabled
} 

// this will show message '0' which is number representation of enum member
alert(States.Active); 

// this will show message 'Disabled' as string representation of enum member
alert(States[States.Disabled]);

更新 1

要从字符串值中获取枚举成员的数值,可以使用以下命令:

var str = "Active";
// this will show message '1'
alert(States[str]);

更新 2

在最新的 TypeScript 2.4 中,引入了字符串枚举,如下所示:

enum ActionType {
    AddUser = "ADD_USER",
    DeleteUser = "DELETE_USER",
    RenameUser = "RENAME_USER",

    // Aliases
    RemoveUser = DeleteUser,
}

有关 TypeScript 2.4 的更多信息,请阅读MSDN 上的博客

于 2014-02-27T14:47:18.453 回答
84

打字稿 2.4+

您现在可以将字符串值直接分配给枚举成员:

enum Season {
    Winter = "winter",
    Spring = "spring",
    Summer = "summer",
    Fall = "fall"
}

有关详细信息,请参阅#15486

打字稿 1.8+

在 TypeScript 1.8+ 中,您可以创建一个字符串字面量类型来定义类型和一个具有相同名称的对象用于值列表。它模仿字符串枚举的预期行为。

这是一个例子:

type MyStringEnum = "member1" | "member2";

const MyStringEnum = {
    Member1: "member1" as MyStringEnum,
    Member2: "member2" as MyStringEnum
};

它将像字符串枚举一样工作:

// implicit typing example
let myVariable = MyStringEnum.Member1; // ok
myVariable = "member2";                // ok
myVariable = "some other value";       // error, desired

// explict typing example
let myExplicitlyTypedVariable: MyStringEnum;
myExplicitlyTypedVariable = MyStringEnum.Member1; // ok
myExplicitlyTypedVariable = "member2";            // ok
myExplicitlyTypedVariable = "some other value";   // error, desired

确保键入对象中的所有字符串!如果您不这样做,那么在上面的第一个示例中,变量不会被隐式键入到MyStringEnum.

于 2016-02-07T18:29:58.357 回答
40

在 TypeScript 0.9.0.1 中,虽然出现编译器错误,但编译器仍然可以将 ts 文件编译成 js 文件。代码按我们的预期工作,Visual Studio 2012 可以支持自动代码完成。

更新 :

在语法上,TypeScript 不允许我们使用字符串值创建枚举,但我们可以破解编译器:p

enum Link
{
    LEARN   =   <any>'/Tutorial',
    PLAY    =   <any>'/Playground',
    GET_IT  =   <any>'/#Download',
    RUN_IT  =   <any>'/Samples',
    JOIN_IN =   <any>'/#Community'
}

alert('Link.LEARN:    '                     + Link.LEARN);
alert('Link.PLAY:    '                      + Link.PLAY);
alert('Link.GET_IT:    '                    + Link.GET_IT);
alert('Link[\'/Samples\']:    Link.'        + Link['/Samples']);
alert('Link[\'/#Community\']    Link.'      + Link['/#Community']);

操场

于 2013-07-24T16:18:39.007 回答
25

打字稿 2.1 +

在 TypeScript 2.1 中引入的Lookup types允许使用另一种模式来模拟字符串枚举:

// String enums in TypeScript 2.1
const EntityType = {
    Foo: 'Foo' as 'Foo',
    Bar: 'Bar' as 'Bar'
};

function doIt(entity: keyof typeof EntityType) {
    // ...
}

EntityType.Foo          // 'Foo'
doIt(EntityType.Foo);   // 
doIt(EntityType.Bar);   // 
doIt('Foo');            // 
doIt('Bar');            // 
doIt('Baz');            //  

打字稿 2.4 +

在 2.4 版本中,TypeScript 引入了对字符串枚举的原生支持,因此不需要上述解决方案。来自 TS 文档:

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}
于 2017-01-13T09:53:06.373 回答
19

为什么不直接使用访问枚举字符串的本机方式。

enum e {
  WHY,
  NOT,
  USE,
  NATIVE
}

e[e.WHY] // this returns string 'WHY'
于 2015-04-17T11:47:47.760 回答
17

您可以在最新的 TypeScript 中使用字符串枚举:

enum e
{
    hello = <any>"hello",
    world = <any>"world"
};

来源:https ://blog.rsuter.com/how-to-implement-an-enum-with-string-values-in-typescript/


更新 - 2016

这些天来,我在 React 中使用的创建一组字符串的一种稍微更健壮的方法是这样的:

export class Messages
{
    static CouldNotValidateRequest: string = 'There was an error validating the request';
    static PasswordMustNotBeBlank: string = 'Password must not be blank';   
}

import {Messages as msg} from '../core/messages';
console.log(msg.PasswordMustNotBeBlank);
于 2015-12-11T10:35:18.193 回答
10

这是一个相当干净的解决方案,允许继承,使用 TypeScript 2.0。我没有在早期版本上尝试过。

奖励:值可以是任何类型!

export class Enum<T> {
  public constructor(public readonly value: T) {}
  public toString() {
    return this.value.toString();
  }
}

export class PrimaryColor extends Enum<string> {
  public static readonly Red = new Enum('#FF0000');
  public static readonly Green = new Enum('#00FF00');
  public static readonly Blue = new Enum('#0000FF');
}

export class Color extends PrimaryColor {
  public static readonly White = new Enum('#FFFFFF');
  public static readonly Black = new Enum('#000000');
}

// Usage:

console.log(PrimaryColor.Red);
// Output: Enum { value: '#FF0000' }
console.log(Color.Red); // inherited!
// Output: Enum { value: '#FF0000' }
console.log(Color.Red.value); // we have to call .value to get the value.
// Output: #FF0000
console.log(Color.Red.toString()); // toString() works too.
// Output: #FF0000

class Thing {
  color: Color;
}

let thing: Thing = {
  color: Color.Red,
};

switch (thing.color) {
  case Color.Red: // ...
  case Color.White: // ...
}
于 2016-10-14T02:39:58.840 回答
9

更新:打字稿 3.4

您可以简单地使用as const

const AwesomeType = {
   Foo: "foo",
   Bar: "bar"
} as const;

打字稿 2.1

这也可以通过这种方式完成。希望它可以帮助某人。

const AwesomeType = {
    Foo: "foo" as "foo",
    Bar: "bar" as "bar"
};

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

console.log(AwesomeType.Bar); // returns bar
console.log(AwesomeType.Foo); // returns foo

function doSth(awesometype: AwesomeType) {
    console.log(awesometype);
}

doSth("foo") // return foo
doSth("bar") // returns bar
doSth(AwesomeType.Bar) // returns bar
doSth(AwesomeType.Foo) // returns foo
doSth('error') // does not compile
于 2017-03-15T20:32:36.800 回答
7

一个hacky的方法是: -

呼叫状态.ts

enum Status
{
    PENDING_SCHEDULING,
    SCHEDULED,
    CANCELLED,
    COMPLETED,
    IN_PROGRESS,
    FAILED,
    POSTPONED
}

export = Status

实用程序.ts

static getEnumString(enum:any, key:any):string
{
    return enum[enum[key]];
}

如何使用

Utils.getEnumString(Status, Status.COMPLETED); // = "COMPLETED"
于 2014-01-23T11:52:25.823 回答
7

这对我有用:

class MyClass {
    static MyEnum: { Value1; Value2; Value3; }
    = {
        Value1: "Value1",
        Value2: "Value2",
        Value3: "Value3"
    };
}

或者

module MyModule {
    export var MyEnum: { Value1; Value2; Value3; }
    = {
        Value1: "Value1",
        Value2: "Value2",
        Value3: "Value3"
    };
}

8)

更新:发布后不久,我发现了另一种方式,但忘记发布更新(但是,上面已经有人提到过):

enum MyEnum {
    value1 = <any>"value1 ", 
    value2 = <any>"value2 ", 
    value3 = <any>"value3 " 
}
于 2013-07-18T17:02:08.520 回答
5

有很多答案,但我没有看到任何完整的解决方案。接受的答案以及 的问题enum { this, one }在于,它会将您碰巧使用的字符串值分散到许多文件中。我也不太喜欢“更新”,它很复杂,也没有利用类型。我认为Michael Bromley 的回答是最正确的,但它的界面有点麻烦,并且可以与类型有关。

我正在使用 TypeScript 2.0.+ ...这就是我要做的

export type Greeting = "hello" | "world";
export const Greeting : { hello: Greeting , world: Greeting } = {
    hello: "hello",
    world: "world"
};

然后像这样使用:

let greet: Greeting = Greeting.hello

使用有用的 IDE 时,它还具有更好的类型/悬停信息。缺点是你必须写两次字符串,但至少它只在两个地方。

于 2017-03-07T13:38:05.787 回答
4

我只是声明一个接口并使用该类型的变量访问枚举。使接口和枚举保持同步实际上很容易,因为 TypeScript 会在枚举中发生变化时抱怨,就像这样。

错误 TS2345:“typeof EAbFlagEnum”类型的参数不可分配给“IAbFlagEnum”类型的参数。“typeof EAbFlagEnum”类型中缺少属性“Move”。

这种方法的优点是不需要类型转换就可以在各种情况下使用枚举(接口),因此支持更多类型的情况,例如开关/案例。

// 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

于 2015-11-17T03:30:23.900 回答
2

打字稿 < 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

到源链接,您可以找到更多更简单的方法来完成字符串文字类型

于 2017-09-08T08:31:51.137 回答
2

使用 typescript@next 中提供的自定义转换器 ( https://github.com/Microsoft/TypeScript/pull/13940 ),您可以使用来自字符串文字类型的字符串值创建类似枚举的对象。

请查看我的 npm 包ts-transformer-enumerate

示例用法:

// The signature of `enumerate` here is `function enumerate<T extends string>(): { [K in T]: K };`
import { enumerate } from 'ts-transformer-enumerate';

type Colors = 'green' | 'yellow' | 'red';
const Colors = enumerate<Colors>();

console.log(Colors.green); // 'green'
console.log(Colors.yellow); // 'yellow'
console.log(Colors.red); // 'red'
于 2017-04-23T15:19:06.220 回答
1

最近使用 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)
于 2014-11-05T23:38:05.590 回答
1

Typescript 中的字符串枚举:

字符串枚举是一个类似的概念,但有一些细微的运行时差异,如下所述。在字符串枚举中,每个成员都必须使用字符串文字或另一个字符串枚举成员进行常量初始化。

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

虽然字符串枚举没有自动递增的行为,但字符串枚举的好处是它们可以很好地“序列化”。换句话说,如果您正在调试并且必须读取数字枚举的运行时值,则该值通常是不透明的 - 它本身并不能传达任何有用的含义(尽管反向映射通常可以提供帮助),字符串枚举允许您在代码运行时提供有意义且可读的值,与枚举成员本身的名称无关。参考链接如下。

在此处输入链接描述

于 2021-06-30T09:35:40.040 回答
1

我有同样的问题,并想出了一个运行良好的功能:

  • 每个条目的键和值都是字符串,并且相同。
  • 每个条目的值都是从键派生的。(即“不要重复自己”,与带有字符串值的常规枚举不同)
  • 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

现在有人可能会问,这个“基于字符串的枚举”比仅仅使用有什么优势:

type Fruit = "apple" | "pear";

有几个优点:

  1. 自动完成更好一点(imo)。例如,如果您键入let fruit = Fruit.,Typescript 将立即列出可用的确切选项集。使用字符串文字,您需要明确定义您的类型,例如。let fruit: Fruit = , 然后按 ctrl+space。(甚至导致不相关的自动完成选项显示在有效选项下方)
  2. 选项的 TSDoc 元数据/描述被转移到MyEnum.XXX字段中!这对于提供有关不同选项的附加信息很有用。例如:
  3. 您可以在运行时访问选项列表(例如Fruit_values,或手动使用Object.values(Fruit))。使用这种type Fruit = ...方法,没有内置的方法可以做到这一点,从而切断了许多用例。(例如,我使用运行时值来构建 json-schemas)
于 2021-06-26T15:09:57.813 回答
1

@basarat 的回答很棒。这是您可以使用的简化但有点扩展的示例:

export type TMyEnumType = 'value1'|'value2';

export class MyEnumType {
    static VALUE1: TMyEnumType = 'value1';
    static VALUE2: TMyEnumType = 'value2';
}

console.log(MyEnumType.VALUE1); // 'value1'

const variable = MyEnumType.VALUE2; // it has the string value 'value2'

switch (variable) {
    case MyEnumType.VALUE1:
        // code...

    case MyEnumType.VALUE2:
        // code...
}
于 2017-03-09T12:01:24.600 回答
0

打字稿 0.9.0.1

enum e{
    hello = 1,
    somestr = 'world'
};

alert(e[1] + ' ' + e.somestr);

打字稿游乐场

于 2013-07-03T19:54:53.600 回答
0

我已经在 TypeScript 1.5 中尝试过,如下所示,它对我有用

module App.Constants {
   export enum e{
        Hello= ("Hello") as any,
World= ("World") as any
    }
}
于 2015-12-04T20:35:47.213 回答
0

我正在寻找一种在打字稿枚举(v2.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
}

...

    GetDescription(e: any, id: number): string {
        return e[e[id].toString() + "Description"];
    }
    getPriceTypeDescription(price: IPricePoint): string {
        return this.GetDescription(PriceTypes, price.priceType);
    }
于 2018-06-26T13:52:16.177 回答
0
//to access the enum with its string value you can convert it to object 
//then you can convert enum to object with proberty 
//for Example :

enum days { "one" =3, "tow", "Three" }

let _days: any = days;

if (_days.one == days.one)
{ 
    alert(_days.one + ' | ' + _days[4]);
}
于 2017-06-13T14:47:35.483 回答
0

小 js-hacky 但有效:e[String(e.hello)]

于 2017-07-02T02:06:29.437 回答
0

非常非常简单的带字符串的枚举(TypeScript 2.4)

import * from '../mylib'

export enum MESSAGES {
    ERROR_CHART_UNKNOWN,
    ERROR_2
}

export class Messages {
    public static get(id : MESSAGES){
        let message = ""
        switch (id) {
            case MESSAGES.ERROR_CHART_UNKNOWN :
                message = "The chart does not exist."
                break;
            case MESSAGES.ERROR_2 :
                message = "example."
                break;
        }
        return message
    }
}

function log(messageName:MESSAGES){
    console.log(Messages.get(messageName))
}
于 2017-08-03T11:15:44.627 回答
0
export enum PaymentType {
                Cash = 1,
                Credit = 2
            }
var paymentType = PaymentType[PaymentType.Cash];
于 2016-03-02T23:53:32.487 回答
0

我认为你应该试试这个,在这种情况下,变量的值不会改变,它的工作方式很像枚举,像类一样使用也可以,唯一的缺点是你可以错误地改变静态变量的值,这就是我们不想在枚举中。

namespace portal {

export namespace storageNames {

    export const appRegistration = 'appRegistration';
    export const accessToken = 'access_token';

  }
}
于 2015-08-20T18:04:41.550 回答
0

如果您想要的主要是简单的调试(通过公平的类型检查)并且不需要为枚举指定特殊值,这就是我正在做的事情:

export type Enum = { [index: number]: string } & { [key: string]: number } | Object;

/**
 * inplace update
 * */
export function enum_only_string<E extends Enum>(e: E) {
  Object.keys(e)
    .filter(i => Number.isFinite(+i))
    .forEach(i => {
      const s = e[i];
      e[s] = s;
      delete e[i];
    });
}

enum AuthType {
  phone, email, sms, password
}
enum_only_string(AuthType);

如果你想支持遗留代码/数据存储,你可以保留数字键。

这样,您可以避免输入两次值。

于 2017-07-04T13:08:55.787 回答