如何模拟基于字符串的枚举

How to simulate a string based enum

我有一个来自 API 的值,它可以是 "orange""apple""banana"

所以首先我创建了一个类型:

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

然后我可以将 API 中的值键入为 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;
}

没关系,但我想避免在开关中手动键入这些字符串。我想要 Fruit.OrangeFruit.AppleFruit.Banana 之类的东西。所以基本上就像一个枚举,但值与字符串而不是数字匹配。

您可以指定枚举的值,但如果它们不是数字,则编译器不会喜欢它。
您可以强制转换为 any 以消除编译错误:

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

另一种选择是使用常规枚举并将接收到的字符串转换为该枚举:

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

从这个老问题中得到答案:

使用 TS 1.8 或更高版本,我们可以执行以下操作:

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

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

然后将其用作 Fruit.Orange 将解析为 "orange"