TypeScript Enum with Multiple Values

Working with TypeScript enums is something I do almost every day, and I’ve discovered that one of the most powerful features is assigning multiple values to enum members.

In this tutorial, I’ll share practical techniques for working with TypeScript enums that hold multiple values.

When I first started using TypeScript years ago, I stuck to basic enums with single values. However, as my projects grew more complex, I needed more sophisticated ways to organize related constants.

TypeScript Enums

Before we get into multiple values, let’s quickly review what a basic enum looks like:

enum USState {
  California = "CA",
  Texas = "TX",
  Florida = "FL"
}

This works well for simple mappings, but what if we need to associate multiple pieces of information with each state?

Method 1: Using Objects as Enum Values

The best way to store multiple values in an enum in TypeScript is to use objects. Here is an example:

enum USState {
  California = 0,
  Texas = 1,
  Florida = 2
}

const StateDetails = {
  [USState.California]: { abbreviation: "CA", capital: "Sacramento", population: 39.5 },
  [USState.Texas]: { abbreviation: "TX", capital: "Austin", population: 29.1 },
  [USState.Florida]: { abbreviation: "FL", capital: "Tallahassee", population: 21.8 }
};

You can then access these values like this:

// Get California's capital
const californiaCapital = StateDetails[USState.California].capital;
console.log(californiaCapital); // "Sacramento"

You can see the exact output in the screenshot below;

typescript enum with multiple values

This approach keeps your enum clean while still associating multiple values with each enum member.

Check out How to Iterate Over Enums in TypeScript?

Method 2: Using Custom Type with String Literal Union

A more type-safe approach involves creating a custom type:

// Define the state abbreviations as a string literal union
type StateAbbreviation = "CA" | "TX" | "FL";

// Create an interface for state details
interface StateInfo {
  fullName: string;
  capital: string;
  population: number;
}

// Map abbreviations to full details
const StateDetails: Record<StateAbbreviation, StateInfo> = {
  "CA": { fullName: "California", capital: "Sacramento", population: 39.5 },
  "TX": { fullName: "Texas", capital: "Austin", population: 29.1 },
  "FL": { fullName: "Florida", capital: "Tallahassee", population: 21.8 }
};

This gives you strong typing while allowing multiple values per state.

Read Convert String to Enum in TypeScript

Method 3: Create a Class-Based Enum Pattern

In TypeScript, you can also create a class-based enum pattern to assign multiple values in a TypeScript enum. For more complex scenarios, I often use a class-based approach. Here is an example.

class USStateEnum {
  static readonly California = new USStateEnum("California", "CA", "Sacramento", 39.5);
  static readonly Texas = new USStateEnum("Texas", "TX", "Austin", 29.1);
  static readonly Florida = new USStateEnum("Florida", "FL", "Tallahassee", 21.8);

  // Get all states as an array
  static getAll(): USStateEnum[] {
    return [this.California, this.Texas, this.Florida];
  }

  // Find a state by any property
  static findByAbbreviation(abbr: string): USStateEnum | undefined {
    return this.getAll().find(state => state.abbreviation === abbr);
  }

  // Private constructor
  private constructor(
    public readonly name: string,
    public readonly abbreviation: string,
    public readonly capital: string,
    public readonly populationInMillions: number
  ) {}
}

Using this pattern:

// Get Florida's details
const florida = USStateEnum.Florida;
console.log(florida.capital); // "Tallahassee"
console.log(florida.populationInMillions); // 21.8

// Find a state by abbreviation
const texas = USStateEnum.findByAbbreviation("TX");
console.log(texas?.name); // "Texas"

This pattern gives you encapsulation, type safety, and helper methods all in one.

You can see the exact output in the screenshot below:

typescript enum with multiple values examples

Check out Check If a String Is in an Enum in TypeScript

Method 4: Using Const Assertions with Tuples

TypeScript 3.4 introduced const assertions, which we can leverage for multi-value enums:

const USStates = {
  California: ["CA", "Sacramento", 39.5] as const,
  Texas: ["TX", "Austin", 29.1] as const,
  Florida: ["FL", "Tallahassee", 21.8] as const
} as const;

// Create type for the keys
type StateName = keyof typeof USStates;

// Access values
const [txAbbr, txCapital, txPop] = USStates.Texas;
console.log(txCapital); // "Austin"

The as const assertion makes the structure deeply immutable and preserves the literal types.

Check out Convert TypeScript Enums to Arrays

Method 5: Using Symbol Properties for Private Values

If you need some values to be internal only, you can use Symbols:

// Symbol for private data
const populationSymbol = Symbol('population');

enum USState {
  California = "CA",
  Texas = "TX",
  Florida = "FL"
}

// Add extra properties
(USState as any)[USState.California] = { capital: "Sacramento", [populationSymbol]: 39.5 };
(USState as any)[USState.Texas] = { capital: "Austin", [populationSymbol]: 29.1 };
(USState as any)[USState.Florida] = { capital: "Tallahassee", [populationSymbol]: 21.8 };

// Helper to get private data
function getStatePopulation(state: USState): number {
  return (USState as any)[state][populationSymbol];
}

console.log((USState as any)[USState.California].capital); // "Sacramento"
console.log(getStatePopulation(USState.California)); // 39.5

This approach is useful when some data should be accessible only through specific functions.

Read Check If a Value Is in an Enum in TypeScript

Real-World Example: User Roles and Permissions

Here’s a practical example of using multi-value enums for user roles in a web application:

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

interface RolePermissions {
  canCreate: boolean;
  canEdit: boolean;
  canDelete: boolean;
  canInvite: boolean;
  displayName: string;
}

const RoleConfig: Record<UserRole, RolePermissions> = {
  [UserRole.Admin]: {
    canCreate: true,
    canEdit: true,
    canDelete: true,
    canInvite: true,
    displayName: "Administrator"
  },
  [UserRole.Editor]: {
    canCreate: true,
    canEdit: true,
    canDelete: false,
    canInvite: false,
    displayName: "Content Editor"
  },
  [UserRole.Viewer]: {
    canCreate: false,
    canEdit: false,
    canDelete: false,
    canInvite: false,
    displayName: "Viewer"
  }
};

// Usage in a component
function UserPermissionsCheck(userRole: UserRole, action: 'create' | 'edit' | 'delete' | 'invite'): boolean {
  const permissionMap = {
    'create': 'canCreate',
    'edit': 'canEdit',
    'delete': 'canDelete',
    'invite': 'canInvite'
  };

  return RoleConfig[userRole][permissionMap[action]];
}

// Check if an editor can delete
console.log(UserPermissionsCheck(UserRole.Editor, 'delete')); // false

This pattern is much cleaner than having separate enums for each permission type.

Read How to Use TypeScript Enum Reverse Mapping

Best Practices for Multi-Value Enums

After years of working with TypeScript enums, I’ve developed these best practices:

  1. Keep the enum itself simple – Use the enum for identifiers and store complex data separately
  2. Use interfaces for type safety – Define interfaces for your multi-value structures
  3. Consider immutability – Use as const or readonly to prevent accidental modifications
  4. Add helper methods – Create utility functions for common operations on your enums
  5. Document the structure – Add JSDoc comments to clarify how the enum and its values work together

Performance Considerations

When working with large enum structures that contain multiple values, performance can become a concern. Here are some tips:

  • For large applications, consider lazy-loading enum data that isn’t needed immediately
  • Use Object.freeze() on objects with multiple values to prevent runtime modifications
  • For complex operations on enum values, memoize results to avoid repeated calculations

In this tutorial, I explained how to work with TypeScript enums that contain multiple values using various methods with examples. I hope these techniques help you as much as they’ve helped me in my TypeScript journey.

You may also like the following tutorials:

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