Check If a String Is in an Enum in TypeScript

While working on an SPFx development project, I got a requirement to check if a string is in an Enum in TypeScript. There are various methods to do so. I will show you here how to check if a string is in an enum in TypeScript with examples.

Enums in TypeScript allow us to define a set of named constants, making our code more readable and self-documenting. TypeScript supports two primary types of enums:

  1. Numeric enums – Where members are assigned incremental numeric values (default starting from 0)
  2. String enums – Where members are initialized with string literals

Here’s a simple example of both:

// Numeric enum
enum Direction {
  North, // 0
  East,  // 1
  South, // 2
  West   // 3
}

// String enum
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

String enums are particularly useful when you need more readable values in runtime code or when integrating with external systems that expect specific string values.

Check If a String Is in an Enum in TypeScript

Now let me show you various methods to check if a string is in an Enum in TypeScript

Method 1: Using Object.values() to Check Enum Membership

One of the most straightforward approaches for checking if a string exists in an enum involves using Object.values() in TypeScript. This method works particularly well with string enums.

enum UserRole {
  Admin = "ADMIN",
  Editor = "EDITOR",
  Viewer = "VIEWER"
}

function isValidUserRole(role: string): boolean {
  return Object.values(UserRole).includes(role as any);
}

// Usage
console.log(isValidUserRole("ADMIN")); // true
console.log(isValidUserRole("GUEST")); // false

This technique is concise and practical for string enums, but it has some limitations when working with numeric enums due to how TypeScript compiles enums to JavaScript.

Here is the exact output in the screenshot below:

Check If a String Is in an Enum in TypeScript

Check out Convert String to Enum in TypeScript

Method 2: Leveraging TypeScript’s Enum Bidirectional Mapping

TypeScript enums have a unique characteristic: they create bidirectional mappings between names and values. We can use this feature to check if a value exists in an enum.

enum MessageType {
  Info = "INFO",
  Warning = "WARNING",
  Error = "ERROR"
}

function isValidMessageType(type: string): boolean {
  // The !! operator converts the result to a boolean
  return !!MessageType[type as keyof typeof MessageType];
}

// Testing the function
console.log(isValidMessageType("Info"));    // true
console.log(isValidMessageType("Warning")); // true
console.log(isValidMessageType("Error"));   // true
console.log(isValidMessageType("Debug"));   // false

Using !!MessageType[type] is a quick way to check if a value exists. However, this approach works better with numeric enums than with string enums due to how TypeScript generates the resulting JavaScript.

You can see the exact output in the screenshot below:

TypeScript Check If a String Is in an Enum

Check out TypeScript Enum Naming Conventions

Method 3: Type-Safe Approach with Custom Type Guards

For a more type-safe solution, we can create a custom type guard function:

enum ProductCategory {
  Electronics = "ELECTRONICS",
  Clothing = "CLOTHING",
  Books = "BOOKS",
  HomeDecor = "HOME_DECOR"
}

function isProductCategory(value: string): value is ProductCategory {
  return Object.values(ProductCategory).includes(value as any);
}

// Usage
function processCategory(category: string) {
  if (isProductCategory(category)) {
    // Inside this block, TypeScript knows category is ProductCategory
    const typeSafeCategory: ProductCategory = category;
    console.log(`Processing category: ${typeSafeCategory}`);
  } else {
    console.log(`Invalid category: ${category}`);
  }
}

This approach provides better type safety and allows TypeScript to narrow the type within conditional blocks.

Read How to Iterate Over Enums in TypeScript?

Method 4: Using a Generic Function for Reusability

To create a reusable solution that works across different enums, we can implement a generic function:

function isInEnum<T extends Record<string, string | number>>(
  enumObject: T,
  value: string | number
): boolean {
  return Object.values(enumObject).includes(value);
}

// Using with different enums
enum PaymentMethod {
  CreditCard = "CREDIT_CARD",
  PayPal = "PAYPAL",
  BankTransfer = "BANK_TRANSFER"
}

enum OrderStatus {
  Pending = "PENDING",
  Processing = "PROCESSING",
  Shipped = "SHIPPED",
  Delivered = "DELIVERED"
}

// Usage
console.log(isInEnum(PaymentMethod, "PAYPAL")); // true
console.log(isInEnum(OrderStatus, "CANCELLED")); // false

This generic function works well for both string and numeric enums, providing a flexible solution you can use throughout your codebase.

You can see the exact output in the screenshot below:

How to Check If a String Is in an Enum in TypeScript

Check out TypeScript Enum Reverse Mapping

Method 5: Handle Case-Insensitive Matching

Sometimes, especially when dealing with user input, you might need case-insensitive matching. Here’s how to implement that:

enum State {
  California = "CALIFORNIA",
  Texas = "TEXAS",
  NewYork = "NEW_YORK",
  Florida = "FLORIDA"
}

function isValidStateIgnoreCase(state: string): boolean {
  const upperCaseState = state.toUpperCase();
  return Object.values(State).some(
    enumValue => (enumValue as string).toUpperCase() === upperCaseState
  );
}

// Usage
console.log(isValidStateIgnoreCase("california")); // true
console.log(isValidStateIgnoreCase("Texas")); // true
console.log(isValidStateIgnoreCase("OHIO")); // false

This approach is beneficial when validating user-provided data where case consistency can’t be guaranteed.

Read TypeScript Enum vs Union Type

Method 6: Using TypeScript’s keyof and typeof Operators

We can combine TypeScript’s keyof and typeof operators for a more type-safe approach:

enum NotificationType {
  Email = "EMAIL",
  SMS = "SMS",
  PushNotification = "PUSH_NOTIFICATION"
}

function isValidNotificationType(type: string): type is NotificationType {
  return (Object.values(NotificationType) as string[]).includes(type);
}

// Alternative approach with keyof and typeof
function isValidNotificationTypeAlt(type: string): type is NotificationType {
  const enumKeys = Object.keys(NotificationType) as Array<keyof typeof NotificationType>;
  return enumKeys.some(key => NotificationType[key] === type);
}

This method provides stronger type checking and better IDE support, making your code more maintainable.

Check out How to Get Key by Value from enum String in Typescript

Performance Considerations When Checking Enum Membership

When working with large enums or in performance-critical code paths, it’s important to consider the efficiency of different validation approaches:

MethodProsConsBest For
Object.values().includes()Simple, readableCreates new array on each callSmall to medium enums
Bidirectional mappingDirect lookup (O(1))Limited to certain enum typesNumeric enums
Set-based lookupFast membership check (O(1))Additional memory for SetFrequently called validations
Type guardsType safetySlightly more verboseApplication code

For high-performance scenarios, consider using a Set-based approach:

enum CarBrand {
  Ford = "FORD",
  Toyota = "TOYOTA",
  Honda = "HONDA",
  BMW = "BMW",
  Mercedes = "MERCEDES",
  Tesla = "TESLA"
}

// Create a Set once (not on every validation call)
const carBrandSet = new Set(Object.values(CarBrand));

function isValidCarBrand(brand: string): boolean {
  return carBrandSet.has(brand as any);
}

// Usage
console.log(isValidCarBrand("FORD")); // true
console.log(isValidCarBrand("Subaru")); // false

This approach provides O(1) lookup time, making it efficient for frequent validations.

Real Example: Form Validation

Now, let me show you a real example of checking if a string is in an Enum in TypeScript. I will take a form validation example.

enum SubscriptionTier {
  Free = "FREE",
  Basic = "BASIC",
  Premium = "PREMIUM",
  Enterprise = "ENTERPRISE"
}

interface UserRegistration {
  username: string;
  email: string;
  tier: string;
}

function validateRegistration(registration: UserRegistration): { valid: boolean; errors: string[] } {
  const errors: string[] = [];
  
  // Other validations...
  
  // Validate subscription tier
  if (!Object.values(SubscriptionTier).includes(registration.tier as any)) {
    errors.push(`Invalid subscription tier. Valid options are: ${Object.values(SubscriptionTier).join(', ')}`);
  }
  
  return {
    valid: errors.length === 0,
    errors
  };
}

// Example usage
const newUser: UserRegistration = {
  username: "john_doe",
  email: "john@example.com",
  tier: "GOLD" // Invalid tier
};

const validationResult = validateRegistration(newUser);
console.log(validationResult.valid); // false
console.log(validationResult.errors); // ["Invalid subscription tier. Valid options are: FREE, BASIC, PREMIUM, ENTERPRISE"]

This pattern is common when validating API requests or form submissions where certain fields must match predefined values.

Conclusion

In this tutorial, I explained how to check if a string is in an Enum in TypeScript using various methods, such as:

  • Using Object.values() to Check Enum Membership
  • Leveraging TypeScript’s Enum Bidirectional Mapping
  • Type-Safe Approach with Custom Type Guards
  • Using a Generic Function for Reusability
  • Handle Case-Insensitive Matching
  • Using TypeScript’s keyof and typeof Operators

You may also like:

Power Apps functions free pdf

30 Power Apps Functions

This free guide walks you through the 30 most-used Power Apps functions with real business examples, exact syntax, and results you can see.

Download User registration canvas app

DOWNLOAD USER REGISTRATION POWER APPS CANVAS APP

Download a fully functional Power Apps Canvas App (with Power Automate): User Registration App