1

I have a string enum and need to check if a literal pertains to the enum. Reverse mapping does not work on string enums.

Supposing

enum Animals{
    cat="c";
    dog="d";
    fish="f";
}

let animal= "d";

is animal a member of Animals ? Considering the enum an object you can iterate and check:

function inEnum(what, enu):boolean{
    for (let item in enu){
        if (enu[item]==what){
            return true;
        }
    }
    return false;
}

Is there a better way?, may this technique break in future versions?

2 Answers 2

3

The ts-enum-util (github, npm) lib supports validation of enum names/values and type-safe value->key and key->value lookups with run-time validation and the option to either throw an error or return a default value.

Examples:

import {$enum} from "ts-enum-util";

enum Animals{
    cat="c";
    dog="d";
    fish="f";
}

let animal= "d"; 

// true
const isAnimal = $enum(Animals).isValue(animal);

// the "isValue" method is a custom type guard
if ($enum(Animals).isValue(animal)) {
    // type of "animal" in here is "Animals" instead of "string"
}

// type: ("cat" | "dog" | "fish")
// value: "dog"
const name = $enum(Animals).getKeyOrThrow(animal); 
Sign up to request clarification or add additional context in comments.

Comments

1

Before answering the question directly, it's worth just mentioning that TypeScript supports a Union Type which is often a better fit for this type of thing than a string enum. Example:

type Animal = 'cat' | 'dog' | 'fish';

let myAnimal1: Animal = 'cat'; // ok
let myAnimal2: Animal = 'buttercup'; // compile-time error "'buttercup' is not assignable to type Animal"

This type of approach has the benefit of letting you know at compile-time whether a value is valid for the Animals type.


Now, to answer your question about determining if a value is in an enum at run-time, we have the in operator which we can use to refactor your inEnum function as follows:

let inEnum = (val, enumObj) => val in enumObj;

inEnum("d", Animals) //evaluates to true
inEnum("z", Animals) //evaluates to false

or even drop the function call altogether and just use the in operator directly:

"d" in Animals //evaluates to true
"z" in Animals //evaluates to false

There is, however, nothing to suggest that your own approach above would ever break in future versions.

1 Comment

With the in operator it's even cleaner using it directly instead of calling a function. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.