Создайте перечисление со строковыми значениями в Typescript
Следующий код может использоваться для создания перечисления в Typescript:
enum e {
hello = 1,
world = 2
};
и к этим значениям можно получить доступ:
e.hello;
e.world;
Как создать перечисление со строковыми значениями?
enum e {
hello = "hello", // error: cannot convert string to e
world = "world" // error
};
Ответы
Ответ 1
TypeScript 2.4
Теперь есть перечисления строк, поэтому ваш код просто работает:
enum E {
hello = "hello",
world = "world"
};
🌹
TypeScript 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"
}
Update:
Исходя из требования, чтобы иметь возможность сделать что-то вроде 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);
Ответ 2
В последней версии (1.0RC) TypeScript вы можете использовать перечисления следующим образом:
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.
Ответ 3
TypeScript 2.4 +
Теперь вы можете напрямую присваивать строковые значения элементам перечисления:
enum Season {
Winter = "winter",
Spring = "spring",
Summer = "summer",
Fall = "fall"
}
Подробнее см. # 15486.
TypeScript 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
.
Ответ 4
В 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']);
Playground
Ответ 5
TypeScript 2.1 +
Типы поиска, введенные в 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('Bad'); // 🙁
TypeScript 2.4 +
В версии 2.4 TypeScript появилась встроенная поддержка перечислений строк, поэтому решение выше не требуется. Из документов TS:
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
Ответ 6
Почему бы просто не использовать собственный способ доступа к строкам перечисления.
enum e {
WHY,
NOT,
USE,
NATIVE
}
e[e.WHY] // this returns string 'WHY'
Ответ 7
Вы можете использовать перечисления строк в последнем 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);
Ответ 8
Здесь довольно чистое решение, которое позволяет наследовать, используя 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: // ...
}
Ответ 9
Это работает для меня:
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 "
}
Ответ 10
Хакерный способ: -
CallStatus.ts
enum Status
{
PENDING_SCHEDULING,
SCHEDULED,
CANCELLED,
COMPLETED,
IN_PROGRESS,
FAILED,
POSTPONED
}
export = Status
Utils.ts
static getEnumString(enum:any, key:any):string
{
return enum[enum[key]];
}
Как использовать
Utils.getEnumString(Status, Status.COMPLETED); // = "COMPLETED"
Ответ 11
Я просто объявляю интерфейс и использую переменную этого типа для доступа к перечислению. Хранение интерфейса и переименование в синхронизации на самом деле легко, поскольку typescript жалуется, что что-то изменяется в перечислении, например.
ошибка TS2345: аргумент типа 'typeof EAbFlagEnum' не может быть назначен к параметру типа "IAbFlagEnum". Свойство "Переместить" отсутствует в типе 'typeof EAbFlagEnum'.
Преимущество этого метода заключается в том, что для использования перечисления (интерфейса) в различных ситуациях не требуется литье типов, и поэтому поддерживаются больше типов ситуаций, таких как коммутатор/случай.
// 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;
Использование переменной, а не enum, дает желаемые результаты.
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
Ответ 12
Typescript 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
Ответ 13
Совсем недавно возникла проблема с 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)
Ответ 14
Там много ответов, но я не вижу никаких полных решений. Проблема с принятым ответом, а также enum { this, one }
заключается в том, что он рассеивает строковое значение, которое вы используете во многих файлах. Мне тоже не нравится "обновление", оно сложное и не использует типы. Я думаю, Майкл Бромли ответ является наиболее правильным, но этот интерфейс немного хлопот и может сделать с типом.
Я использую 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. Обратный вывод состоит в том, что вам нужно написать строки дважды, но, по крайней мере, это только в двух местах.
Ответ 15
@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...
}
Ответ 16
С настраиваемыми трансформаторами (https://github.com/Microsoft/TypeScript/pull/13940), который доступен в typescript @next, вы можете создать объект с перечислением со строковыми значениями из строковых литералов.
Пожалуйста, загляните в мой пакет 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'
Ответ 17
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!
from https://basarat.gitbooks.io/typescript/docs/types/literal-types.html
К исходной ссылке вы можете найти более простые способы выполнения строкового литерала
Ответ 18
Я думаю, вы должны попробовать с этим, в этом случае значение переменной не изменится, и оно работает совсем как перечисления, используя, как класс, также работает единственный недостаток, по ошибке вы можете изменить значение статической переменной и что мы не хотим перечислять.
namespace portal {
export namespace storageNames {
export const appRegistration = 'appRegistration';
export const accessToken = 'access_token';
}
}
Ответ 19
Я пробовал в Typescript 1.5, как показано ниже, и это сработало для меня
module App.Constants {
export enum e{
Hello= ("Hello") as any,
World= ("World") as any
}
}
Ответ 20
export enum PaymentType {
Cash = 1,
Credit = 2
}
var paymentType = PaymentType[PaymentType.Cash];
Ответ 21
Я придумал такое решение:
// Utils.ts
export function convertEnumValuesToString(obj) {
Object.keys(obj).forEach(function (key) {
if (isNaN(+key)) {
Object.defineProperty(obj, key, {
value: key,
enumerable: true
});
}
});
return obj;
}
// actions/hello.ts
import { convertEnumValuesToString } from '../utils'
export enum actionTypes {
GREETING,
FAREWELL_INIT,
FAREWELL_DONE
}
console.log(actionTypes .GREETING) // 0
convertEnumValuesToString(actionTypes); // override to same key-based string values
console.log(actionTypes .GREETING) // "GREETING"
Ответ 22
Супер простое решение
enum MySeasons {
WINTER,
SPRING,
SUMMER,
FALL
}
let season = MySeasons[0]; //"WINTER"
Ответ 23
//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]);
}
Ответ 24
Маленький js-hacky, но работает: e[String(e.hello)]
Ответ 25
Если вы хотите в основном легко отлаживать (с довольно проверкой типа) и не нужно указывать специальные значения для перечисления, это то, что я делаю:
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);
Если вы хотите поддерживать устаревший код/хранилище данных, вы можете хранить цифровые клавиши.
Таким образом, вы можете не вводить значения дважды.
Ответ 26
Очень, очень, очень просто Enum со строкой (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))
}
Ответ 27
Typescript 0.9.0.1
enum e{
hello = 1,
somestr = 'world'
};
alert(e[1] + ' ' + e.somestr);
Typescript Игровая площадка