How to Convert a TypeScript Enum to a Number (With Examples)

The simplest way to convert TypeScript enum to number values is to read the member itself: a numeric enum member already is a number at runtime, so const n: number = OrderStatus.Shipped works with no cast. String enums are different, and need a lookup map:

const n: number = OrderStatus.Shipped;   // 2

Nothing below is hand-typed output: I ran each file through TypeScript 7.0.2 and Node.js v22.22.2 with --strict on, then copied the console text.

Convert a numeric enum to a number

Members of a numeric enum get numbers automatically, starting at 0 unless you set a value. Here Pending starts at 1, so the next two count up:

enum OrderStatus {
  Pending = 1,
  Shipped,          // 2
  Delivered,        // 3
  Cancelled = 9,
}

const current = OrderStatus.Shipped;

const a: number = current;         // no cast needed
const b = Number(current);         // explicit
const c = +current;               // unary plus

console.log(a, b, c, typeof a);
console.log("next step:", OrderStatus.Shipped + 1);
console.log(JSON.stringify({ orderId: 50217, city: "Denver", status: current }));

Output:

2 2 2 number
next step: 3
{"orderId":50217,"city":"Denver","status":2}
Command Prompt output of a TypeScript numeric enum member assigned to number, Number() and unary plus, all printing 2
All three forms print 2, and typeof confirms it’s a plain number.

Number() and + don’t change the value; they just make the intent obvious. It’s also what lands in JSON. For the basics of declaring enums, see my TypeScript enums guide.

Why does an enum name string fail to index the enum?

Names often arrive as text, say from a CSV column. Indexing the enum with a plain string doesn’t compile in strict mode:

enum OrderStatus { Pending = 1, Shipped, Delivered, Cancelled = 9 }

const fromCsv: string = "Shipped";
const code = OrderStatus[fromCsv];

Output:

enum_keyfail.ts(4,26): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
Command Prompt output of tsc error TS7015 when indexing a TypeScript numeric enum with a string variable
TS7015: a string could be anything, so TypeScript won’t index the enum with it.

The compiler needs a key it can trust. Turning free text into an actual enum member is its own topic, which I cover in converting a string to an enum in TypeScript.

Convert an enum name to its number with keyof typeof

keyof typeof OrderStatus gives the union of member names. A known literal works directly; untrusted input needs a check first:

enum OrderStatus { Pending = 1, Shipped, Delivered, Cancelled = 9 }

type StatusName = keyof typeof OrderStatus;   // "Pending" | "Shipped" | ...

const known: StatusName = "Delivered";
console.log("known name:", OrderStatus[known]);

function statusCode(name: string): number | undefined {
  if (!Object.hasOwn(OrderStatus, name)) return undefined;
  const value = OrderStatus[name as StatusName];
  return typeof value === "number" ? value : undefined;
}

for (const input of ["Shipped", "shipped", "toString", "2"]) {
  console.log(JSON.stringify(input).padEnd(11), "->", statusCode(input));
}
console.log('OrderStatus["2"] =', (OrderStatus as Record<string, unknown>)["2"]);

Output:

known name: 3
"Shipped"   -> 2
"shipped"   -> undefined
"toString"  -> undefined
"2"         -> undefined
OrderStatus["2"] = Shipped

Object.hasOwn() blocks inherited names like toString. The typeof check matters because numeric enums also store reverse entries, so "2" returns the name Shipped, not a number. That’s explained in reverse mapping in TypeScript enums.

If keyof typeof looks odd, my keyof operator guide breaks it down.

Convert a string enum to a number

String enum members hold text, so Number() and + compile fine but quietly return NaN. Map each member to its number instead:

enum Plan {
  Basic = "BASIC",
  Pro = "PRO",
  Team = "TEAM",
}

console.log("Number(Plan.Pro):", Number(Plan.Pro));
console.log("+Plan.Pro:       ", +Plan.Pro);

const planTier: Record<Plan, number> = {
  [Plan.Basic]: 1,
  [Plan.Pro]: 2,
  [Plan.Team]: 3,
};
const monthlyUsd: Record<Plan, number> = {
  [Plan.Basic]: 9,
  [Plan.Pro]: 29.5,
  [Plan.Team]: 79.99,
};

for (const p of Object.values(Plan)) {
  console.log(p.padEnd(5), "tier", planTier[p], `$${monthlyUsd[p].toFixed(2)}`);
}

enum ZipPrefix { Chicago = "606", Austin = "787" }   // digits stored as text
const prefix = Number(ZipPrefix.Austin);
console.log("Austin prefix:", prefix, Number.isNaN(prefix) ? "(not numeric)" : "(ok)");

Output:

Number(Plan.Pro): NaN
+Plan.Pro:        NaN
BASIC tier 1 $9.00
PRO   tier 2 $29.50
TEAM  tier 3 $79.99
Austin prefix: 787 (ok)
Command Prompt output of a TypeScript string enum giving NaN with Number(), then tier numbers and USD prices from a Record lookup map
Number(Plan.Pro) is NaN; the Record<Plan, number> maps return real numbers.

Record<Plan, number> also protects you later. If you add a member to Plan, the compiler flags every map that’s missing it. When the text is digits, like ZIP prefixes, Number() works, but still check for NaN.

More string parsing rules are in converting a string to a number in TypeScript. Need several values per member? See enums with multiple values.

Get a number from a const enum

A const enum disappears at compile time. TypeScript pastes the number wherever you use a member, which you can see in the emitted JavaScript:

const enum Speed {
  Slow = 25,
  Normal = 55,
  Highway = 70,
}

const limit: number = Speed.Highway;
console.log("limit:", limit, "mph");

Output:

"use strict";
const limit = 70 /* Speed.Highway */;
console.log("limit:", limit, "mph");
limit: 70 mph
Command Prompt showing compiled JavaScript where a TypeScript const enum member is inlined as the number 70
The compiled file has no Speed object, just 70 and a comment with the member name.

With no object at runtime, there’s no reverse mapping or Object.values(). The compiler stops a reverse lookup, and an out-of-range literal too:

const enum Speed { Slow = 25, Normal = 55, Highway = 70 }

const typed: Speed = 99;
const label = Speed[70];

Output:

enum_constfail.ts(3,7): error TS2322: Type '99' is not assignable to type 'Speed'.
enum_constfail.ts(4,21): error TS2476: A const enum member can only be accessed using a string literal.

Tools that compile one file at a time (isolatedModules) restrict const enums, so I keep them for internal constants.

Check that a number is a valid enum value

Going the other way is where bugs hide. A literal 7 is rejected, but any number variable is accepted, so values from an API slip through:

enum OrderStatus { Pending = 1, Shipped, Delivered, Cancelled = 9 }

const fromApi: number = 7;
const unchecked: OrderStatus = fromApi;       // compiles, but 7 isn't a member
console.log("unchecked:", unchecked, OrderStatus[unchecked]);

const codes = Object.values(OrderStatus).filter(
  (v): v is OrderStatus => typeof v === "number"
);
console.log("all codes:", codes);

function isOrderStatus(n: number): n is OrderStatus {
  return (codes as number[]).includes(n);
}

for (const n of [2, 7, 9]) {
  console.log(n, isOrderStatus(n) ? `valid (${OrderStatus[n]})` : "rejected");
}

Output:

unchecked: 7 undefined
all codes: [ 1, 2, 3, 9 ]
2 valid (Shipped)
7 rejected
9 valid (Cancelled)

Filtering Object.values() to numbers drops the reverse-mapping names, and the n is OrderStatus guard narrows the type. The pattern is explained in the is keyword in TypeScript, and listing members is in getting all enum values.

Which enum to number method should you use?

Enum kindHow to get the numberWatch out for
Numeric enumRead the member, or Number() for claritynumber values aren’t checked
Name as a stringkeyof typeof + Object.hasOwnReverse-mapping keys like "2"
String enumRecord<Enum, number> mapNumber() returns NaN
Const enumRead the member (inlined)No runtime object at all

For switch logic over the codes, see switch statements on TypeScript enums. If you keep writing converters, enums vs string literal unions may change your mind.

These enum guides pair well with this one:

Frequently asked questions

How do I convert a TypeScript enum to a number?

For a numeric enum, read the member: const n: number = Status.Active. It’s already a number, so Number() is optional.

Why does Number() return NaN for my enum?

It’s a string enum, so the member holds text like "PRO". Use a Record<Enum, number> lookup map instead.

How do I get the number from an enum name string?

Check the name with Object.hasOwn(), index with name as keyof typeof Enum, and confirm typeof value === "number".

Can I convert a const enum member to a number?

Yes. The compiler inlines the number, so const n: number = Speed.Highway becomes 70. Reverse lookups aren’t possible.

Does TypeScript check that a number is a valid enum value?

Only for literals. A number variable is assignable to a numeric enum without a check, so validate it with a type guard.

Where are TypeScript enums documented?