Question

How to Convert a String to an Enum in TypeScript

Question

I have defined the following enum in TypeScript:

enum Color {
  Red,
  Green
}

In a function, I receive a color value as a string. For example:

const green = "Green";
const color: Color = <Color>green; // Error: cannot convert string to enum

How can I safely convert a string value like "Green" into the corresponding Color enum value in TypeScript?

Short Answer

By the end of this page, you will understand why a plain string cannot be directly cast to a TypeScript enum, how enum lookup works, and how to safely convert strings into enum values using validation. You will also learn common patterns used in real TypeScript codebases to avoid runtime bugs.

Concept

TypeScript enums are named sets of constant values. In your example:

enum Color {
  Red,
  Green
}

Color.Red is actually 0, and Color.Green is 1 because numeric enums start at 0 by default.

That means this enum is not storing the strings "Red" and "Green". It is storing numeric values with named members.

So when you write:

const green = "Green";
const color: Color = green as Color;

TypeScript may allow a type assertion in some cases, but that does not actually convert the string at runtime. A type assertion only tells the compiler, "trust me." It does not change the value.

This matters because:

  • "Green" is a string
  • Color.Green is the number 1
  • assigning one to the other without conversion is unsafe

To convert a string to an enum, you usually need to look up the enum member by its name:

const color = Color[green as keyof typeof Color];

For numeric enums, this returns the numeric enum value.

However, because user input can be invalid, real code should also validate the string before using it.

Mental Model

Think of an enum like a labeled storage rack:

  • The label Red points to value 0
  • The label Green points to value 1

If someone gives you the text "Green", you do not automatically have the value 1. You first need to go to the rack and ask:

"Do you have a label named Green? If yes, give me the value behind it."

That is what enum lookup does.

A type assertion like green as Color is like writing 1 on a sticky note and placing it on top of the string. The original value is still just the string "Green". Nothing has been converted.

Take Quiz

Syntax and Examples

Basic enum lookup

enum Color {
  Red,
  Green
}

const input = "Green";
const color = Color[input as keyof typeof Color];

console.log(color); // 1
console.log(color === Color.Green); // true

How it works

  • typeof Color gets the type of the enum object
  • keyof typeof Color means the valid enum keys: "Red" | "Green"
  • Color[input as keyof typeof Color] looks up the member by name

Safer version with validation

enum Color {
  Red,
  Green
}

function parseColor(value: string): Color | undefined {
  if (value in Color && isNaN(Number(value))) {
    return Color[value as keyof typeof Color] as Color;
  }

  return undefined;
}

console.log(parseColor("Green")); // 1
console.log(parseColor("Blue")); // undefined

This is safer because it does not assume every string is valid.

String enum example

Sometimes you want the enum values themselves to be strings:

enum Color {
  Red = "Red",
  Green = "Green"
}

function parseColor(value: string): Color | undefined {
  if (Object.values(Color).includes(value as Color)) {
    return value as Color;
  }

  return undefined;
}

console.log(parseColor("Green")); // "Green"

With a string enum, the value is already a string, so conversion is often simpler.

Step by Step Execution

Consider this example:

enum Color {
  Red,
  Green
}

const input = "Green";
const result = Color[input as keyof typeof Color];

Here is what happens step by step:

  1. TypeScript compiles the numeric enum into an object similar to this:
{
  0: "Red",
  1: "Green",
  Red: 0,
  Green: 1
}
  1. input contains the string "Green".

  2. input as keyof typeof Color tells TypeScript to treat input as a valid enum key.

  3. Color["Green"] is evaluated.

  4. The enum object returns 1.

  5. result now contains 1, which is the value of Color.Green.

So:

console.log(result); // 1
console.log(result === Color.Green); // true

If the input were "Blue", then:

Color["Blue" as keyof typeof Color]

would return undefined at runtime, which is why validation is important.

Real World Use Cases

String-to-enum conversion is common whenever your program receives text from outside your code.

Common examples

  • API request parameters: a query string might contain "Green"
  • Form input: a dropdown or text field may send enum names as strings
  • Configuration files: JSON often stores values as strings
  • URL parameters: /products?color=Green
  • Environment variables: values always arrive as strings
  • CLI tools: command-line options are text input

Example: parsing an API filter

enum Status {
  Pending,
  Approved,
  Rejected
}

function parseStatus(value: string): Status | undefined {
  if (value in Status && isNaN(Number(value))) {
    return Status[value as keyof typeof Status] as Status;
  }
  return undefined;
}

This helps convert external text into a controlled internal value your app can trust.

Take Quiz

Real Codebase Usage

In real projects, developers rarely cast raw input directly. They usually wrap conversion in a helper function and validate the input first.

Common patterns

Guard clause

function parseColor(value: string): Color | undefined {
  if (!(value in Color) || !isNaN(Number(value))) {
    return undefined;
  }

  return Color[value as keyof typeof Color] as Color;
}

This rejects invalid input early.

Validation before business logic

const parsedColor = parseColor(userInput);

if (parsedColor === undefined) {
  throw new Error("Invalid color value");
}

saveColor(parsedColor);

Mapping external values to internal enums

Sometimes incoming values do not match enum member names exactly.

enum Color {
  Red,
  Green
}

const colorMap: Record<string, Color> = {
  red: Color.Red,
  green: Color.Green
};

function parseColor(value: string): Color | undefined {
  return colorMap[value.toLowerCase()];
}

This is very common when handling user input that may use lowercase or different formatting.

Prefer string enums for external data

If your app exchanges values with APIs or JSON, string enums are often easier to work with:

enum Color {
  Red = "Red",
  Green = "Green"
}

They are more readable and avoid confusion caused by numeric values like 0 and 1.

Common Mistakes

1. Thinking as converts the value

Broken example:

enum Color {
  Red,
  Green
}

const input = "Green";
const color = input as Color;

Problem:

  • This does not convert "Green" into 1
  • It only changes what TypeScript believes about the type

2. Skipping validation

Broken example:

const input = "Blue";
const color = Color[input as keyof typeof Color];
console.log(color); // undefined

Problem:

  • invalid input leads to undefined
  • later code may fail unexpectedly

Fix it by checking first.

function parseColor(value: string): Color | undefined {
  if (value in Color && isNaN(Number(value))) {
    return Color[value as keyof typeof Color] as Color;
  }
  return undefined;
}

3. Forgetting that numeric enums have reverse mappings

Numeric enums create both key-to-value and value-to-key mappings. That can make checks like value in Color slightly confusing, because numbers also appear as keys on the enum object.

4. Using enum names when values are actually strings

If you define:

enum Color {
  Red = "RED",
  Green = "GREEN"
}

Then "Green" is not a valid enum value. The valid values are "RED" and "GREEN".

5. Ignoring case differences

Broken example:

parseColor("green");

If your enum key is Green, lowercase green will not match unless you normalize the input.

function parseColor(value: string): Color | undefined {
  const normalized = value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
  if (normalized in Color) {
    return Color[normalized as keyof typeof Color] as Color;
  }
  return undefined;
}

Comparisons

Enum conversion approaches

ApproachWorks for numeric enumWorks for string enumSafe by defaultNotes
value as ColorNo real conversionNo real conversionNoType assertion only
Color[value as keyof typeof Color]YesLooks up by key, not valueNoAdd validation
Object.values(Color).includes(value as Color)LimitedYesBetterUseful for string enums
Manual map objectYesYesYesGreat for normalization and custom input

Numeric enum vs string enum

Enum typeExample valueGood forDrawback
Numeric enumColor.Green === 1internal flags or compact valuesless readable when serialized
String enumColor.Green === "Green"APIs, JSON, config, logsslightly more verbose

Enum vs union of string literals

OptionExampleBenefitLimitation
Enumenum Color { Red = "Red" }named constants and groupingextra runtime object
String union`type Color = "Red""Green"`simple and lightweight

In many modern TypeScript codebases, string unions are often preferred when you only need type safety and not enum behavior.

Take Quiz

Cheat Sheet

Numeric enum lookup

enum Color {
  Red,
  Green
}

const input = "Green";
const color = Color[input as keyof typeof Color]; // 1

Safe parser for numeric enum

function parseColor(value: string): Color | undefined {
  if (value in Color && isNaN(Number(value))) {
    return Color[value as keyof typeof Color] as Color;
  }
  return undefined;
}

String enum parser

enum Color {
  Red = "Red",
  Green = "Green"
}

function parseColor(value: string): Color | undefined {
  return Object.values(Color).includes(value as Color)
    ? (value as Color)
    : undefined;
}

Key rules

  • as does not convert values at runtime
  • numeric enums store numbers by default
  • Color["Green"] works because enum keys are object properties
  • validate external input before using it
  • prefer string enums for API and JSON data
  • use a manual mapping object when you need case-insensitive or custom parsing

Common edge cases

  • "green" does not match "Green"
  • invalid keys return undefined
  • numeric enums have reverse mappings
  • string enums do not have reverse mappings like numeric enums do

FAQ

How do I convert a string to an enum in TypeScript?

Use enum lookup or a parser function. For a numeric enum, Color[input as keyof typeof Color] looks up the enum member by name.

Why does as Color not work?

Because type assertions only affect TypeScript's type checking. They do not transform the runtime value.

What happens if the string does not match an enum member?

The lookup usually returns undefined, so you should validate the input first.

Is a string enum easier to use than a numeric enum?

Usually yes, especially for API data, JSON, and form values, because the runtime values are readable strings.

Can I do case-insensitive enum parsing?

Yes. Normalize the input first, or use a mapping object like { green: Color.Green }.

Should I use enums or string literal unions?

If you only need type safety, string literal unions are often simpler. If you want a grouped runtime object, enums can be useful.

Do numeric enums and string enums behave the same way?

No. Numeric enums support reverse mapping. String enums do not behave the same way at runtime.

Take Quiz

Mini Project

Description

Build a small TypeScript utility that parses user-provided color strings into enum values. This demonstrates safe conversion, input normalization, and validation, which are all common when handling form input, query parameters, or API values.

Goal

Create a reusable parseColor function that converts a string into a valid Color enum value or returns undefined when the input is invalid.

Requirements

  • Define a Color enum with at least Red, Green, and Blue.
  • Accept user input as a string.
  • Support case-insensitive input such as "green" or "GREEN".
  • Return undefined for invalid values.
  • Print a message showing whether parsing succeeded.
Take Quiz

Keep learning

Related questions

View more