Typescript Enums

In TypeScript, enums (enumerations) are a powerful tool for defining sets of named constants. They enhance code readability, maintainability, and type safety by providing a clear structure for representing a collection of related values. This chapter delves into enums, exploring their creation, usage, and advanced features.

Basic Enums

Creating Enums

You can create an enum using the enum keyword followed by a name and curly braces {} containing the enum members:

				
					enum Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

				
			

Numeric Enums (Default Behavior)

By default, enums are numeric. The first member starts at 0, and subsequent members are automatically assigned incremented values:

				
					console.log(Weekday.Monday);  // Output: 0
console.log(Weekday.Tuesday); // Output: 1
console.log(Weekday.Wednesday); // Output: 2

				
			

Initializing Enum Members

You can explicitly assign values to enum members:

				
					enum Weekday {
  Monday = 1,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

				
			
				
					console.log(Weekday);

/* Output:
{
  '1': 'Monday',
  '2': 'Tuesday',
  '3': 'Wednesday',
  '4': 'Thursday',
  '5': 'Friday',
  '6': 'Saturday',
  '7': 'Sunday',
  Monday: 1,
  Tuesday: 2,
  Wednesday: 3,
  Thursday: 4,
  Friday: 5,
  Saturday: 6,
  Sunday: 7
}
*/

				
			

Now, Monday has the value 1, and subsequent members continue automatic incrementation from there.

Fully Initialized Enums

To assign specific values to all members, provide values for each:

				
					enum HttpStatusCode {
  OK = 200,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404
}

				
			
				
					console.log(HttpStatusCode);

/* Output:
{
  '200': 'OK',
  '400': 'BadRequest',
  '401': 'Unauthorized',
  '404': 'NotFound',
  OK: 200,
  BadRequest: 400,
  Unauthorized: 401,
  NotFound: 404
}
*/

				
			

String Enums

Enums can also contain string values:

				
					enum FileType {
  PDF = "pdf",
  DOCX = "docx",
  TXT = "txt"
}

				
			

Accessing Enum Values

By Name

Use the enum name followed by the dot (.) and member name:

				
					enum Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

const today = Weekday.Wednesday;
console.log(today); // Output: 2 (or "Wednesday" for string enums)

				
			

Reverse Lookup (Optional)

Enums provide optional reverse lookup to get the member name based on its value (not recommended for readability):

				
					enum HttpStatusCode {
  OK = 200,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404
}

const statusCode = 401;
const statusName = HttpStatusCode[statusCode]; // statusName will be "Unauthorized"


				
			

Using Enums

Type Safety

Enums ensure type safety by restricting variables to only allowed enum values:

				
					enum Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

let day: Weekday;
day = Weekday.Thursday; // Valid
day = "Saturday"; // Error: Type '"Saturday"' is not assignable to type 'Weekday'

				
			

Switch Statements

Enums are ideal for switch statements:

				
					enum Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

function getWeekendGreeting(day: Weekday) {
  switch (day) {
    case Weekday.Saturday:
    case Weekday.Sunday:
      return "Enjoy your weekend!";
    default:
      return "Have a productive day!";
  }
}

console.log(getWeekendGreeting(Weekday.Friday)); // Output: "Have a productive day!"
console.log(getWeekendGreeting(Weekday.Saturday)); // Output: "Enjoy your weekend!"

				
			

Advanced Enums

Const Enums

const enums are optimized for compile-time usage, reducing runtime overhead:

				
					const enum Color {
  Red = "red",
  Green = "green",
  Blue = "blue"
}

				
			

However, they cannot be used for reverse lookup or with typeof.

Computed Enum Members

You can use expressions to define enum member values dynamically:

				
					enum HttpStatus {
  OK = 200,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  ServerError = 500 + Math.floor(Math.random() * 100) // Random value between 500 and 599
}

				
			

Enums with Methods

While enums are primarily for constants, you can add methods for basic operations within the enum definition. However, use this approach cautiously, as it can blur the lines between enums and classes:

				
					enum File {
  TXT,
  PDF,
  DOCX,
  getExtension(this: File) {
    switch (this) {
      case File.TXT:
        return ".txt";
      case File.PDF:
        return ".pdf";
      case File.DOCX:
        return ".docx";
    }
  }
}

console.log(File.TXT.getExtension()); // Output: ".txt"

				
			

Enums and Interfaces

Enums can be used as types within interfaces to enforce stricter type checking:

				
					interface Product {
  name: string;
  price: number;
  category: FileType; // Enum used as a type
}

const product: Product = {
  name: "My Book",
  price: 19.99,
  category: FileType.PDF // Ensures category is a valid FileType
};

				
			

Enums and Generics

Enums can be used with generics to create flexible data structures:

				
					function identify<T extends string | number>(value: T, type: { [key: string]: T }) {
  return type[value as keyof typeof type]; // Enum used as keyof
}

const fileType = identify("txt", FileType); // fileType will be ".txt"
const statusCodeString = identify(404, HttpStatusCode); // statusCodeString will be "NotFound"

				
			

Mapped Types and Enums

Combine mapped types with enums to create objects with properties based on enum values:

				
					type WeekdayGreetings = {
  [key in Weekday]: string;
};

const greetings: WeekdayGreetings = {
  [Weekday.Monday]: "Hello, Monday!",
  // ... greetings for other weekdays
};

console.log(greetings[Weekday.Tuesday]); // Output: (greeting for Tuesday)

				
			

Enums and Utility Types

Use enums with utility types like Partial<T> or Pick<T, K> to create subsets of enum values:

				
					type WorkingDays = Partial<Weekday>; // WorkingDays allows any subset of Weekday values
type Weekend = Pick<Weekday, Weekday.Saturday | Weekday.Sunday>; // Weekend allows only Saturday and Sunday

const today: WorkingDays = Weekday.Wednesday; // Valid
const tomorrow: Weekend = Weekday.Sunday; // Valid

				
			

Best Practices for Enums

  • Use clear and descriptive names for enums and their members.
  • Consider using string enums when readability is more important than numeric values.
  • Use const enums for compile-time optimization when appropriate.
  • Use computed enum members sparingly for complex scenarios.
  • Avoid adding too much logic within enum methods; consider separate classes for complex functionality.

By effectively utilizing TypeScript enums and their advanced features, you can enhance code readability, maintainability, and type safety in your TypeScript projects. Remember to choose the right approach based on your specific requirements and maintain a balance between simplicity and advanced usage. Happy coding !❤️

Table of Contents