สร้าง enum ด้วยค่าสตริง


262

รหัสต่อไปนี้สามารถใช้ในการสร้าง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 
};

คำตอบ:


409

TypeScript 2.4

ตอนนี้มี enums สตริงเพื่อให้รหัสของคุณทำงาน:

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

🌹

TypeScript 1.8

ตั้งแต่ TypeScript 1.8 คุณสามารถใช้ชนิดตัวอักษรของสตริงเพื่อมอบประสบการณ์ที่เชื่อถือได้และปลอดภัยสำหรับค่าสตริงที่มีชื่อ (ซึ่งบางส่วนใช้ enums)

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

การสนับสนุนแบบดั้งเดิม

Enums ใน 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); 

ปรับปรุงเล็กน้อย:toString(): string { return this.value; }
psulek

@psulek ที่จริง typescript จะอนุมานว่าtoStringส่งกลับสตริงตั้งแต่มันกลับมาthis.valueและvalueเป็นสตริงประเภท ดังนั้นคุณจึงไม่สามารถทำvar x:number = E.hello.toString();และถ้าคุณทำvar x = E.hello.toString();x ถูก infered จะเป็นชนิดstringเช่นกัน :)
basarat

2
@BASarat นี่เป็นความจริงที่ typescript จัดการกับกรณีเช่นนี้ แต่ฉันหมายถึงมีวิธีการตกแต่งด้วยประเภทผลตอบแทนทุกครั้งที่เรารู้แม้ว่าจะไม่จำเป็นสำหรับผู้แปล TS แต่สำหรับพวกเราที่รู้ว่าเมื่อเราเห็นนิยามของวิธีการ พิมพ์มันส่งคืน
psulek

@basarat มีข้อเสียในการแทนที่get()วิธีด้วยreturn this.valueหรือไม่ วิธีการที่จะกลับค่าสตริงเมื่อใดก็ตามที่เข้าถึงได้และไม่เพียง toString()แต่เมื่อมีการแปลง
จอห์น

@basarat หากคุณมี "enums" หลายอย่างเช่นนั้นคอมไพเลอร์จะไม่แยกความแตกต่างระหว่างพวกเขาเพราะโครงสร้างการพิมพ์ - คอมไพเลอร์จะเห็นvalueสมาชิกในทุกประเภทและถือว่าพวกเขาเป็นประเภทเทียบเคียง คุณสามารถทำให้valueสมาชิกส่วนตัวแม้ว่า วิธีนี้คอมไพเลอร์จะมองไม่เห็นและจะไม่พยายามใช้การพิมพ์โครงสร้าง
Kirill G.

113

ในเวอร์ชันล่าสุด (1.0RC) ของ TypeScript คุณสามารถใช้ enums ดังนี้:

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

ในการรับค่าตัวเลขของสมาชิก enum จากค่าสตริงคุณสามารถใช้สิ่งนี้:

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

อัปเดต 2

ใน TypeScript 2.4 ล่าสุดมีการแนะนำ enums สตริงดังนี้:

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

    // Aliases
    RemoveUser = DeleteUser,
}

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ typescript 2.4 อ่านบล็อกใน MSDN


2
โดยทั่วไปแล้วโซลูชันนี้เป็นที่ต้องการ (เนื่องจากเป็น enum จริง) อย่างไรก็ตามคุณมีข้อ จำกัด อย่างมากเกี่ยวกับชื่อ enum (ซึ่งก็คือ 'สตริง')
JasonS

2
ทางออกที่ดีที่สุด ณ วันนี้
Alon Amir

2
มีอะไรใหม่ในเรื่องนี้? เพราะStates[str]ปัจจุบันใช้งานไม่ได้ Type 'string' is not assignable to type 'States'
MrCroft

1
@MrCroft คุณสามารถใช้: States[str as any]เพื่อทำใน typescript เวอร์ชันปัจจุบัน (2.x)
psulek

States [str] คือสิ่งที่ฉันกำลังมองหา ขอบคุณ!
Martin Konicek

81

TypeScript 2.4+

ตอนนี้คุณสามารถกำหนดค่าสตริงโดยตรงกับสมาชิก enum:

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

ดู# 15486สำหรับข้อมูลเพิ่มเติม

TypeScript 1.8+

ใน TypeScript 1.8+ คุณสามารถสร้างประเภทตัวอักษรสตริงเพื่อกำหนดประเภทและวัตถุที่มีชื่อเดียวกันสำหรับรายการของค่า มันเลียนแบบพฤติกรรมที่คาดหวังของ enum สตริง

นี่คือตัวอย่าง:

type MyStringEnum = "member1" | "member2";

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

ซึ่งจะทำงานเหมือน enum สตริง:

// 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ถ้าคุณทำไม่ได้แล้วในตัวอย่างแรกข้างต้นตัวแปรจะไม่ถูกพิมพ์โดยปริยาย


1
ฉันจะกำหนดสิ่งที่คล้ายกันในไฟล์ประกาศได้อย่างไร
Zev Spitz

@ZevSpitz คุณสามารถทำนี้
เดวิด Sherret

น่าสังเกตว่าด้วยคอมไพเลอร์ปัจจุบันคุณสามารถพิมพ์ค่าสตริงใน MyStringEnum และจะไม่บ่น ฉันได้สร้างอินเทอร์เฟซ 'ผู้ปฏิบัติการ' เพื่อให้แน่ใจว่าสตริงของฉันใช้ได้ตลอดเวลา ตัวอย่างเช่น: อินเทอร์เฟซ MyStringEnumEnforcer {Member1: MyStringEnum, Member2: MyStringEnum} จากนั้นคอมไพเลอร์อาจสิ้นสุดลงสำหรับ MyStringEnum: MyStringEnumEnforcer = {Member1: "member1", Member2: "member2" สถานการณ์เดิมในที่สุด มันมีพิธีมากมายด้วยวิธีนี้ แต่ฉันชอบความปลอดภัย
jmorc


40

ใน TypeScript 0.9.0.1 แม้ว่ามันจะเกิดข้อผิดพลาดของคอมไพเลอร์คอมไพเลอร์ยังสามารถรวบรวมไฟล์ ts ลงในไฟล์ js รหัสทำงานได้ตามที่เราคาดไว้และ Visual Studio 2012 สามารถรองรับการกรอกรหัสอัตโนมัติ

อัปเดต:

ในไวยากรณ์ TypeScript ไม่อนุญาตให้เราสร้าง enum ด้วยค่าสตริง แต่เราสามารถแฮ็คคอมไพเลอร์: 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']);

สนามเด็กเล่น


1
แฮ็คที่ดี แต่คุณไม่สามารถใช้ค่า enum / ค่าคงที่เหล่านี้ในคำสั่งสวิตช์เช่นcase Link.LEARN:จะได้รับCannot convert 'Link.LEARN' to 'string'ข้อผิดพลาดในการสร้าง การหล่อจะไม่ทำงาน
Gone Coding

@TrueBlueAussie ดูเหมือนว่าจะทำงานได้ดีสำหรับฉันที่ใช้ TSC 1.0.0.0 นอกจากนี้ถ้าด้วยเหตุผลบางอย่างคุณต้องใส่ค่าคงที่สตริง / ตัวแปรในคำสั่ง case มันจะทำงานถ้าคุณส่งไปยังใด ๆ
CodeAndCats

1
นอกจากนี้ขอบคุณ @ zjc0816 ฉันรักความรักการแก้ปัญหานี้ :)
CodeAndCats

นั่นคือทางออกที่ฉันต้องการ
Murhaf Sousli

5
ตลกฉันสงสัยว่าทำไม TypeScript ไม่เพียงรองรับ enum สตริงแล้ว ... ผู้คนจำนวนมากต้องการสิ่งนี้ (ฉันรวมอยู่ด้วย)
Hendy Irawan

23

TypeScript 2.1 +

ประเภทการค้นหาที่แนะนำใน TypeScript 2.1 อนุญาตรูปแบบอื่นสำหรับการจำลอง enums สตริง:

// 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 แนะนำการสนับสนุนดั้งเดิมสำหรับ enums สตริงดังนั้นจึงไม่จำเป็นต้องแก้ปัญหาข้างต้น จากเอกสาร TS:

enum Colors {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE",
}

ฉันจะทำสิ่งนี้ได้อย่างไรถ้าชื่อคีย์ enum แตกต่างจากค่าสตริง (เพราะมันยาวมาก)
CletusW

ไม่เป็นไร! แก้ไขได้ในคำตอบของ @ Łukasz-pniewski ด้านล่างstackoverflow.com/a/42820134/1431146
CletusW

tslint จะโยนข้อผิดพลาดในตัวอย่างของ String-Enum เมื่อพยายามที่จะย้อนกลับแมป Enum: องค์ประกอบโดยนัยมีประเภท 'ใด ๆ ' เพราะการแสดงออกของดัชนีไม่ได้เป็นประเภท 'จำนวน' ฉันเดาว่าปัญหาคือใน TS string Enums ไม่สามารถย้อนกลับได้ดูความคิดเห็นในตัวอย่าง String-Enum ที่typescriptlang.org/docs/handbook/release-notes/ … - นี่น่าจะเป็นจริงสำหรับ TS 2.4 String-Enum ถูกนำเสนอ แต่ฉันยังได้รับข้อผิดพลาดใน TS 2.6.2 ตัวอย่าง: Colors["RED"]จะไม่ทำงาน ความคิดใด ๆ วิธีการแก้ปัญหานี้ (จำเป็นสำหรับการแปลง JSON)
masi

19

ทำไมไม่ใช้วิธีดั้งเดิมในการเข้าถึงสตริงของ enum

enum e {
  WHY,
  NOT,
  USE,
  NATIVE
}

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

2
นี่คือคำตอบที่ฉันกำลังมองหาขอบคุณ! โซลูชันอื่น ๆ เป็นวิธีการแก้ปัญหาที่ชาญฉลาด แต่วิธีนี้ง่ายมาก :)
M--

19
นี่ไม่ได้ตอบคำถาม คำถามไม่เกี่ยวกับการเข้าถึงสตริงของ enum enum Why { Because = "You Can't", Always = "Do Things That Way." };)
James Wilkins

มีปัญหาเมื่อใช้ค่าตัวเลข enums เช่น 0 เป็นเท็จ, ยากที่จะแก้ปัญหาและอื่น ๆ
robmcm

@robmcm แก้ไข enum e {WHY = 1, NOT = 2, USE = 3, NATIVE = 4} e [e.WHY] // นี่จะคืนค่าสตริง 'WHY'
Mient-jan Stelling

16

คุณสามารถใช้ string enums ใน 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);

1
นี่เป็นวิธีที่รัดกุมที่สุดที่ทำงานให้ฉัน ... อย่างน้อยก็จนกว่าฉันจะสามารถหาวิธีอัปเดตนั่งร้านของฉันเพื่อคอมไพล์กับ TS 1.8 ได้
ThinkBonobo

อย่างไรก็ตามปัญหาหนึ่งของสิ่งนี้คือสิ่งที่<string>e.helloทำให้เกิดข้อผิดพลาด e.helloยังคงถือว่าเป็นตัวเลขโดยคอมไพเลอร์ <number>e.helloทำงานได้แม้ว่า มีวิธีแก้ไขไหม? <string><any>e.helloทั้งหมดที่ฉันสามารถคิด
RainingChain

ปัญหาอื่นคือเมื่อมีสมาชิก enum เท่ากับมูลค่า enum Ex:enum Test { a = <any>"b", b = <any>"c", c = <any>"a" } Test.a === 'c'
RainingChain

ฉันใช้วิธีนี้ตลอดเวลา String enum ของหิน เป็นเรื่องน่าผิดหวังที่คอมไพเลอร์ไม่มีการสนับสนุนชั้นหนึ่งสำหรับตัวอักษรสตริง แต่มีการสนับสนุนชั้นสอง คอมไพเลอร์รู้จริงเมื่อคุณใช้การแฮ็ก <any> เนื่องจากจะทำให้คุณไม่สามารถใช้งานได้ในไฟล์. d.ts - ซึ่งสำหรับฉันนั้นทำให้ฉันมีความชอบธรรมในการใช้ "แฮ็ค" เนื่องจากผู้แปลทราบอย่างชัดเจน ของมัน แต่ไม่ได้หยุดอย่างสมบูรณ์
CodeAndCats

Btw ถ้าคุณต้องการเปรียบเทียบค่าสตริงกับค่า enum ของสตริงแทนที่จะส่งไปยัง<any>แล้ว<string>เพียงทำ:someStringValue == someEnumValue.toString()
CodeAndCats

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: // ...
}

1
คำตอบที่ดี! ฉันพยายามดิ้นรนเพื่อทำให้วัตถุคล้าย Enum ด้วยการสนับสนุนการสืบทอด
DanielM

ตัวอย่างการใช้คลาส Enum: goo.gl/SwH4zb (ลิงก์ไปยังสนามเด็กเล่นของ TypeScript)
DanielM

8

วิธีแฮ็คนี้คือ: -

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"

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 " 
}

4

ฉันเพิ่งประกาศอินเตอร์เฟสและใช้ตัวแปรประเภทการเข้าถึง enum การรักษาอินเทอร์เฟซและ enum ให้ตรงกันนั้นง่ายจริง ๆ เนื่องจาก TypeScript บ่นว่ามีบางสิ่งเปลี่ยนแปลงใน enum เช่นนั้น

ข้อผิดพลาด TS2345: อาร์กิวเมนต์ประเภท 'typeof EAbFlagEnum' ไม่สามารถกำหนดให้กับพารามิเตอร์ประเภท 'IAbFlagEnum' คุณสมบัติ 'ย้าย' หายไปในประเภท 'typeof EAbFlagEnum'

ข้อดีของวิธีนี้คือไม่จำเป็นต้องใช้การหล่อแบบเพื่อใช้ enum (อินเตอร์เฟส) ในสถานการณ์ต่าง ๆ และสนับสนุนสถานการณ์ประเภทอื่นเช่นสวิตช์ / ตัวพิมพ์

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


นี่เป็นคำตอบเดียวที่ฉันพบซึ่งอนุญาตให้ผสมคำจำกัดความกับการนำเข้า ดี! คุณสามารถใช้export default EAbFlagEnum as IAbFlagEnum;แทนการประกาศตัวแปรซ้ำได้ ฉันยังลบ<any>นักแสดงใน enum มันใช้งานได้ดี
Guillaume F.

4

ปรับปรุง: TypeScript 3.4

คุณสามารถใช้as const:

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

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

นี่คือสิ่งที่ฉันต้องการ! สนับสนุนการมีชื่อคีย์แตกต่างจากค่าสตริงตามที่คุณแสดงด้วยความแตกต่างตัวพิมพ์ใหญ่ / ตัวพิมพ์เล็ก ขอบคุณ!
CletusW

2

ด้วยตัวแปลงแบบกำหนดเอง ( https://github.com/Microsoft/TypeScript/pull/13940 ) ซึ่งมีอยู่ใน typescript @ ถัดไปคุณสามารถสร้าง enum เช่นวัตถุที่มีค่าสตริงจากชนิดตัวอักษรสตริง

โปรดมองเข้าไปในแพคเกจของฉัน NPM, TS-หม้อแปลงการระบุ

ตัวอย่างการใช้งาน:

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

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

ไปยังลิงค์แหล่งที่มาคุณสามารถค้นหาวิธีที่จะทำให้สตริงตัวอักษรเป็นจริงได้ง่ายขึ้น


2

มีคำตอบมากมาย แต่ฉันไม่เห็นวิธีแก้ปัญหาที่สมบูรณ์ ปัญหาเกี่ยวกับคำตอบที่ได้รับการยอมรับเช่นกัน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 ที่เป็นประโยชน์ การถอยกลับคือคุณต้องเขียนสตริงสองครั้ง แต่อย่างน้อยก็มีแค่สองแห่งเท่านั้น


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...
}

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)

0

ฉันคิดว่าคุณควรลองกับสิ่งนี้ในกรณีนี้ค่าของตัวแปรจะไม่เปลี่ยนแปลงและมันใช้งานได้เหมือน enums การใช้งานเหมือนกับคลาสยังมีข้อเสียเพียงอย่างเดียวคือโดยไม่ได้ตั้งใจคุณสามารถเปลี่ยนค่าของตัวแปรแบบคงที่ได้ เราไม่ต้องการเป็นจำนวนเงิน

namespace portal {

export namespace storageNames {

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

  }
}


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]);
}


0

หากสิ่งที่คุณต้องการส่วนใหญ่จะเป็นการดีบั๊กง่าย (ด้วยการตรวจสอบอย่างเป็นธรรม) และไม่จำเป็นต้องระบุค่าพิเศษสำหรับ enum นี่คือสิ่งที่ฉันกำลังทำอยู่:

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);

หากคุณต้องการสนับสนุนรหัส / ที่เก็บข้อมูลแบบดั้งเดิมคุณอาจเก็บคีย์ตัวเลขไว้

ด้วยวิธีนี้คุณสามารถหลีกเลี่ยงการพิมพ์ค่าสองครั้ง


0

ง่ายมาก ๆ , 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))
}

0

ฉันได้ลองใน TypeScript 1.5 เหมือนด้านล่างแล้วมันใช้ได้สำหรับฉัน

module App.Constants {
   export enum e{
        Hello= ("Hello") as any,
World= ("World") as any
    }
}

0

ฉันกำลังมองหาวิธีที่จะใช้คำอธิบายใน typescript enums (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);
    }

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.