Finally, an easy way to use TypeScript enums

Cubicle Buddha - Jul 15 '19 - - Dev Community

One of the best things that TypeScript provides is a standard enum type that simply doesn't exist in JavaScript. Yes, yes... there are thousands of enum libraries out there in Github with various implementations. But there's something wonderful about having a standard built into the language.

tl;dr: I'm going to show a cool library that makes interacting with enums a joyous experience.

So what's the problem?

Well, as great as TypeScript enums are... they've lead to some verbose or unreadable code.

Like, let's say you have an enum for food ordering:

export enum FoodPreference {
    vegan,
    vegetarian,
    meatEater
}
Enter fullscreen mode Exit fullscreen mode

Beautiful. But now you need to write some presentation logic. Let's first show a simple but highly-unreadable way to write that presentation logic:

const presentationString = filter === FoodPreference.vegan
            ? 'Do you have a nut preference?'
            : filter === FoodPreference.vegetarian
            ? 'Which protein would you like?'
            : 'What type of meat would you like?';
Enter fullscreen mode Exit fullscreen mode

So, just like how people have food preferences... some people love nested ternaries. I am not one of those people.

While I love the immutability benefits that come with const, there are serious problems with the "eye-scan-ability" of nested ternaries. Furthermore, I recently described how fall-through approaches like that example put the code at risk for when a new case has been added to the enum.

The more readable, more defensive, but sadly verbose option

So we could rewrite the above code using our defensive technique by using the assertUnreachable function I described in my other article:

function askFirstQuestion(pref: FoodPreference): string {
    switch(pref){
        case(FoodPreference.vegan): {
            return 'Do you have a nut preference?';
        }
        case(FoodPreference.vegetarian): {
            return 'Which protein would you like?';
        }
        case(FoodPreference.meatEater): {
            return 'What type of meat would you like?'
        }
        default: {
            assertUnreachable(pref)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Hmmm, that's still a lot of typing. I don't even like switch cases that much because of known issues like falling through. And although assertUnreachable eliminates a lot of the problems with switch cases, I still feel like we can do better.

Look up in the sky! It's ts-enum-util to the rescue!

Some wonderful person decided to make a library that would simplify many enum operations. Check out their readme for more information, but for the moment let's see how this ts-enum-util improves our code:

function createPresentationString(pref: FoodPreference): string {
    return $enum.mapValue(pref).with({
        [FoodPreference.vegan]: 'Do you have a nut preference?',
        [FoodPreference.vegetarian]: 'Which protein would you like?',
        [FoodPreference.meatEater]: 'What type of meat would you like?',
    })
}
Enter fullscreen mode Exit fullscreen mode

Isn't that much clearer? It's certainly shorter.

So is this just about less code?

Wait, before you say that it's just syntactic sugar... let's show the TLC (tender, love, and care) that the library author added to their library.

Watch what happens when you add a new entry into the enum:

Isn't that cool? We get all of the benefits of assertUnreachable without the readability problems of nested ternaries or the verbosity (and other known issues) of switch statements.

Thoughts?

So I'm a big fan of this new approach. But I'm interested in hearing your thoughts so please reply on twitter or in the comments. Also, be sure to throw a Github star or two to Jeff Lau's ts-enum-util library.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player