empz
empz

Reputation: 11808

How to simulate a string based enum

I have a value that comes from an API that could be either "orange", "apple" or "banana".

So first I created a type as:

type Fruit = "orange" | "apple" | "banana";

So then I can type the value from the API as Fruit;

type Fruit = "orange" | "apple" | "banana";

function getFruitFromApi(): Fruit {
    // simulating random result
    const fruits: Fruit[] = ["orange", "apple", "banana"];

    return fruits[Math.floor(Math.random() * 3)];
}

const fruit: Fruit = getFruitFromApi();

switch (fruit) {
    case "orange": break;
    case "apple": break;
    case "banana": break;
}

That's okay but I'd like to avoid having to type those strings manually in the switch. I'd like to have something like Fruit.Orange, Fruit.Apple and Fruit.Banana. So basically like an enum but with the values matched with strings instead of numbers.

Upvotes: 0

Views: 240

Answers (2)

empz
empz

Reputation: 11808

Taking the answer from this old question: https://stackoverflow.com/a/35257367/105937

With TS 1.8 or later we can do the following:

type Fruit = "orange" | "apple" | "banana";

const Fruit = {
    Orange: "orange" as Fruit,
    Apple:  "apple" as Fruit,
    Banana: "banana"  as Fruit
};

And then use it as Fruit.Orange which will be resolved to "orange".

Upvotes: 2

Nitzan Tomer
Nitzan Tomer

Reputation: 164337

You can specify the values of an enum, but if they are not numbers then the compiler won't like it.
You can cast to any to remove compilation errors:

enum Fruit {
    Orange = "orange" as any,
    Apple = "apple" as any,
    Banana = "banana" as any
}

function getFruitFromApi(): Fruit {
    const fruits = ["orange", "apple", "banana"];

    return fruits[Math.floor(Math.random() * 3)] as any;
}

Another option is to use a regular enum and to convert the received string into that enum:

enum Fruit {
    Orange,
    Apple,
    Banana
}

function getFruitFromApi(): Fruit {
    const fruits = ["orange", "apple", "banana"];
    const fruit = fruits[Math.floor(Math.random() * 3)];

    for (var key in Fruit) {
        if (typeof key === "string" && key.toLowerCase() === fruit) {
            return (Fruit as any)[key];
        }
    }

    return null;
}

const fruit: Fruit = getFruitFromApi();

switch (fruit) {
    case Fruit.Orange:
        console.log("orange");
        break;
    case Fruit.Apple:
        console.log("apple");
        break;
    case Fruit.Banana:
        console.log("banana");
        break;
}

Upvotes: 0

Related Questions