TypeScript - צור Enum עם ערכי מחרוזת
הקוד הבא יכול לשמש ליצירת 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
};
תשובה #1
TypeScript 2.4
כעת ישנם enums של מחרוזות כך שהקוד שלך פשוט עובד:
enum E {
hello = "hello",
world = "world"
};
🌹
TypeScript 1.8
מאז TypeScript 1.8 ניתן להשתמש בסוגי מחרוזת מילולית כדי לספק חוויה אמינה ובטוחה עבור ערכי מחרוזת ממוספרים (שזה חלקית למה שמשתמשים במקראי enum).
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);
תשובה #2
בגרסה האחרונה (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.
תשובה #3
TypeScript 2.4+
כעת אתה יכול להקצות ערכי מחרוזת ישירות לחברי האנומ:
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.
תשובה #4
ב-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']);
מִגרָשׂ מְשָׂחָק
תשובה #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('Bar'); // 👍
doIt('Baz'); // 🙁
TypeScript 2.4 +
עם גרסה 2.4, TypeScript הציגה תמיכה מקורית באנומים של מחרוזות, ולכן הפתרון שלמעלה אינו נדרש. מתוך התיעוד של TS:
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
תשובה #6
למה לא פשוט להשתמש בדרך המקומית לגישה למחרוזות של enum.
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 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
תשובה #9
הנה פתרון די נקי שמאפשר הירושה, באמצעות 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: // ...
}
