Reputation: 7222
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?
Upvotes: 1
Views: 2667
Reputation: 442
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);
Upvotes: 3
Reputation: 14495
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.
Upvotes: 1