Hone logo
Hone
Problems

Advanced Enum Utilities in TypeScript

Enums in TypeScript provide a way to define a set of named constants. However, TypeScript's built-in enum support can be limited for complex scenarios. This challenge asks you to create a set of utility functions to enhance the functionality of enums, enabling more flexible and powerful usage within your TypeScript projects.

Problem Description

You are tasked with creating a module containing utility functions for working with TypeScript enums. These utilities should provide the following functionalities:

  1. values<T extends Enum>: A function that takes an enum type T as input and returns an array containing all the values of the enum.
  2. keys<T extends Enum>: A function that takes an enum type T as input and returns an array containing all the keys (enum member names) of the enum.
  3. valueOf<T extends Enum, K extends keyof T>: A function that takes an enum type T and a key K of that enum, and returns the value associated with that key. This should provide type safety, ensuring the key is a valid member of the enum.
  4. isIn<T extends Enum, V>: A function that takes an enum type T and a value V, and returns true if V is a value of the enum T, and false otherwise.

An Enum type is defined as a type that is an instance of EnumConstructor. EnumConstructor is a type that represents a constructor function that returns an enum.

Key Requirements:

  • The functions must be type-safe, leveraging TypeScript's type system to provide compile-time checks.
  • The functions should handle both numeric and string-based enums correctly.
  • The functions should be generic, allowing them to work with any enum type.
  • The code should be well-documented and easy to understand.

Expected Behavior:

  • values should return an array of the enum's values in the order they are defined.
  • keys should return an array of the enum's keys in the order they are defined.
  • valueOf should return the correct value for a given key. If the key is invalid, it should throw a type error.
  • isIn should correctly identify whether a value is a valid enum value.

Edge Cases to Consider:

  • Enums with no members.
  • Enums with both numeric and string values.
  • Invalid keys passed to valueOf.
  • Values that are not enum values passed to isIn.

Examples

Example 1:

enum Color {
  Red = 1,
  Green = 2,
  Blue = 3,
}

// Using the utilities
const colorValues = values(Color);
const colorKeys = keys(Color);
const redValue = valueOf(Color, Color.Red);
const isInRed = isIn(Color, 1);
const isInYellow = isIn(Color, 4);

// Expected Output:
// colorValues: [1, 2, 3]
// colorKeys: ["Red", "Green", "Blue"]
// redValue: 1
// isInRed: true
// isInYellow: false

Example 2:

enum Status {
  Pending = "pending",
  Active = "active",
  Completed = "completed",
}

// Using the utilities
const statusValues = values(Status);
const statusKeys = keys(Status);
const activeValue = valueOf(Status, Status.Active);
const isInActive = isIn(Status, "active");
const isInInactive = isIn(Status, "inactive");

// Expected Output:
// statusValues: ["pending", "active", "completed"]
// statusKeys: ["Pending", "Active", "Completed"]
// activeValue: "active"
// isInActive: true
// isInInactive: false

Example 3: (Edge Case)

enum EmptyEnum { }

const emptyValues = values(EmptyEnum);

// Expected Output:
// emptyValues: []

Constraints

  • The solution must be written in TypeScript.
  • The code should be well-formatted and readable.
  • The utility functions should be implemented within a single module.
  • The solution should not rely on external libraries.
  • The values and keys functions should return arrays in the order the enum members are defined.

Notes

  • Consider using TypeScript's reflection capabilities (e.g., Object.keys, Object.values) to extract enum information. However, be mindful of type safety and potential limitations.
  • Think about how to handle both numeric and string-based enums in a generic way.
  • Pay close attention to type safety when implementing valueOf and isIn. Use conditional types and type guards to ensure correctness.
  • The EnumConstructor type is a helper type to ensure type safety. You don't need to explicitly define it, but it's useful to understand the underlying concept.
Loading editor...
typescript