以下代码可用于在 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
};
打字稿 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);
在 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 的更多信息,请阅读 blog on MSDN。
States[str]
现在不起作用。 Type 'string' is not assignable to type 'States'
States[str as any]
在当前(2.x)版本的 Typescript 中执行。
打字稿 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
。
在 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']);
case Link.LEARN:
将得到 Cannot convert 'Link.LEARN' to 'string'
构建错误。铸造将不起作用。
打字稿 2.1 +
Lookup types,在 TypeScript 2.1 中引入,允许模拟字符串枚举的另一种模式:
// 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",
}
Colors["RED"]
将不起作用。知道如何解决这个问题(JSON 转换需要)。
为什么不直接使用访问枚举字符串的本机方式。
enum e {
WHY,
NOT,
USE,
NATIVE
}
e[e.WHY] // this returns string 'WHY'
enum Why { Because = "You Can't", Always = "Do Things That Way." }
;)
您可以在最新的 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);
<string>e.hello
会触发错误。 e.hello
仍然被编译器视为一个数字。 <number>e.hello
确实有效。有没有办法解决?我能想到的只有<string><any>e.hello
。
enum Test { a = <any>"b", b = <any>"c", c = <any>"a" }
Test.a === 'c'
<any>
然后转换为 <string>
,只需执行以下操作:someStringValue == someEnumValue.toString()
这是一个相当干净的解决方案,允许继承,使用 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: // ...
}
更新:打字稿 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
一个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"
这对我有用:
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 "
}
有很多答案,但我没有看到任何完整的解决方案。接受的答案以及 enum { this, one }
的问题在于,它会将您碰巧使用的字符串值分散到许多文件中。我也不太喜欢“更新”,它很复杂,也没有利用类型。我认为 Michael Bromley's answer 是最正确的,但它的接口有点麻烦,并且可以与类型有关。
我正在使用 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 时,它还具有更好的类型/悬停信息。缺点是你必须写两次字符串,但至少它只在两个地方。
Greeting
类型(即按名称),而不仅仅是“通过具有相同的匹配一组文字值”。没什么大不了的,但值得一提。 (例如,有些人可能希望对该答案使用相同的“转换为命名类型”方法)
我只是声明一个接口并使用该类型的变量访问枚举。使接口和枚举保持同步实际上很容易,因为 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
export default EAbFlagEnum as IAbFlagEnum;
而不是重新声明变量。我还删除了枚举中的 <any>
演员,它工作正常。
使用 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'
打字稿 < 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 中的字符串枚举:
字符串枚举是一个类似的概念,但有一些细微的运行时差异,如下所述。在字符串枚举中,每个成员都必须使用字符串文字或另一个字符串枚举成员进行常量初始化。
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
虽然字符串枚举没有自动递增的行为,但字符串枚举的好处是它们可以很好地“序列化”。换句话说,如果您正在调试并且必须读取数字枚举的运行时值,则该值通常是不透明的 - 它本身并不能传达任何有用的含义(尽管反向映射通常可以提供帮助),字符串枚举允许您在代码运行时提供有意义且可读的值,与枚举成员本身的名称无关。参考链接如下。
@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...
}
最近使用 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)
我有同样的问题,并想出了一个运行良好的功能:
每个条目的键和值都是字符串,并且相同。
每个条目的值都是从键派生的。 (即“不要重复自己”,与带有字符串值的常规枚举不同)
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";
有几个优点:
自动完成更好一点(imo)。例如,如果您键入 let fruit = Fruit.,Typescript 将立即列出可用的确切选项集。使用字符串文字,您需要明确定义您的类型,例如。 let fruit: Fruit = ,然后按 ctrl+space。 (甚至会导致不相关的自动完成选项显示在有效选项下方)选项的 TSDoc 元数据/描述被转移到 MyEnum.XXX 字段!这对于提供有关不同选项的附加信息很有用。例如:您可以在运行时访问选项列表(例如 Fruit_values,或手动使用 Object.values(Fruit))。使用类型 Fruit = ... 方法,没有内置的方法可以做到这一点,这会切断许多用例。 (例如,我使用运行时值来构建 json-schemas)
我认为你应该试试这个,在这种情况下,变量的值不会改变,它的工作方式很像枚举,像类一样使用也可以,唯一的缺点是你可以错误地改变静态变量的值,这就是我们不想在枚举中。
namespace portal {
export namespace storageNames {
export const appRegistration = 'appRegistration';
export const accessToken = 'access_token';
}
}
export enum PaymentType {
Cash = 1,
Credit = 2
}
var paymentType = PaymentType[PaymentType.Cash];
//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]);
}
小 js-hacky 但有效:e[String(e.hello)]
如果您想要的主要是简单的调试(通过公平的类型检查)并且不需要为枚举指定特殊值,这就是我正在做的事情:
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);
如果你想支持遗留代码/数据存储,你可以保留数字键。
这样,您可以避免输入两次值。
非常非常简单的带字符串的枚举(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))
}
我已经在 TypeScript 1.5 中尝试过,如下所示,它对我有用
module App.Constants {
export enum e{
Hello= ("Hello") as any,
World= ("World") as any
}
}
打字稿 0.9.0.1
enum e{
hello = 1,
somestr = 'world'
};
alert(e[1] + ' ' + e.somestr);
Cannot convert 'string' to 'e'.
。
我正在寻找一种在打字稿枚举(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);
}
toString(): string { return this.value; }
toString
返回一个字符串,因为它返回this.value
并且value
是字符串类型。所以你不能做var x:number = E.hello.toString();
并且如果你做var x = E.hello.toString();
x 也被推断为string
类型:)return this.value
替换get()
方法有什么缺点吗?这样,它会在访问时返回字符串值,而不仅仅是在转换toString()
时。value
成员并将它们视为可比较的类型。不过,您可以将value
成员设为私有。这样编译器就不会看到它,也不会尝试应用结构类型。