1

Context lets say I have the following enum with string values:

enum Fruit {
  Apple = "apple",
  Orange = "orange",
  Banana = "banana",
  Pear = "pear"
}

the user always inputs the literal string value ("apple", "banana", "orange", "pear") lets say from a drop down to eliminate possibility of invalid inputs - which I need to convert back to type Fruit i.e. something like this:

function getFruit(fruit: string): Fruit {
    switch (fruit) {
        case "apple":
        return Fruit.Apple
        case "banana":
        return Fruit.Banana
        case "orange":
        return Fruit.Orange
        case "pear":
        return Fruit.Pear
        default:
        // I DON'T WANT THIS!
        return Fruit.Pear
    }
}

Problems

  • The switch statement requires maintenance overhead
  • The getFruit() function:
    • takes any string which is not represented as a union of acceptable string values (typescript will not throw a compilation error if anything other than "apple", "banana", "orange", "pear" are used.) I know i can use a union of absolute strings as the type but thats even more overhead.
    • a default case needs to be provided and a default result returned.

Question

Is there a more elegant way to do the above? maybe with type/typeof/keyof or any other operations?

I ideally want to be able to:

  • Eliminate the switch statement completely - (so no maintenance overhead)
  • getFruit() function to only take string values that are contained in the enum programatically (without manually declaring and maintaining a union of absolute strings).

p.s. I don't care if i need to use an alternative type rather than an enum - its the functionality that is important!

Best Attempt the closest I've got to a solution so far is:

type Fruits = "apple" | "banana" | "orange" | "pear"
let Fruit = {
  Apple = "apple",
  Orange = "orange",
  Banana = "banana",
  Pear = "pear"
}
type Fruit = keyof typeof Fruit

function parseFruit(fruit: Fruits): Fruit {
  return Object.keys(Fruit).find((key) => {
    return Fruit[key as Fruit] === fruit
  }) as Fruit
}

this still requires for string literal union type Fruits and Fruit to be managed. This solution would be 'perfect' if I could figure out how to programmatically create the string literal union type Fruits.

SagarScript
  • 1,145
  • 11
  • 15
  • Why do you need the keys at all? Just use `type Fruit = "apple" | "banana" | "orange" | "pear"` and then `getFruit()` is just the identity function (`const getFruit = fruit: Fruit => fruit`) and therefore unnecessary, like [this](https://tsplay.dev/wgZEBW). Can you demonstrate a use case where the enum is actually helping you? – jcalz Aug 02 '22 at 01:55

1 Answers1

-1

You can iterate over Enum values and find Fruit

function getFruit(fruit: string): Fruit | null {
    return Object.values(Fruit).find(item => item === fruit) ?? null
}