Tony
Tony

Reputation: 38381

TypeScript enum conversion / casting

This statement fails. How could I cast from one enum into another (which are identical)

enum Enum1 {
  Key1 = 'key'
}

enum Enum2 {
  Key1 = 'key'
}

const key = Enum1.Key1
const key2 = key as Enum2

Upvotes: 9

Views: 15431

Answers (5)

gg405
gg405

Reputation: 51

Here is a solution that works for number values. However, note this is "dangerous" as there is no confirmation/validation about the conversion occurring, so probably doesn't satisfy your desire for compile-time checking. The bottom line is you have to cast to some intermediate compatible type (number, string, any, unknown) before casting to 2nd enum, and by so doing, you have detached any meaningful semantic checking. Anytime you cast you are giving up compile time checking by definition.

enum SeverityLevel {
    Verbose = 0,
    Warning = 1
}

enum InternalSeverity {
    Verbose = 0,
    Warning = 1
}


function CallMe(severity: SeverityLevel) {
    console.log(`SeverityLevel: ${severity}`);
}

function Convert(severity: InternalSeverity) {
    console.log(severity);
    console.log(SeverityLevel[severity]);
    console.log(InternalSeverity[severity]);

    CallMe(severity as number as SeverityLevel);
}

Convert(InternalSeverity.Warning);

Output

It might be better to write a verbose conversion function that maps values explicitly and can check that, for example, warning is the same in both enums, like so:

switch (severity) {
   case SeverityLevel.Warning:
      return InternalSeverity.Warning;
      break;

This allows conversion between enums, is resilient to changes in the underlying values (assuming the purpose of the enum is to use names to represent values and that the values themselves are irrelevant) and satisfies compile time checks (insofar as if someone removes the key from the enum it will break). If the values are more important than the names, then you may need a slightly different approach.

Upvotes: 5

OoDeLally
OoDeLally

Reputation: 599

It seems indeed that Typescript doesn't bother checking the possible values, so it doesn't notice these enums are compatible. What I am doing right now is

const key2 = key as Enum1 & Enum2

It is not perfect, since it does not enforce the enum's compatibility. However still better than widening to string or any.

Upvotes: 0

altumano
altumano

Reputation: 2735

You can cast to string first and then to the desired enum:

const key2 = key as string as Enum2

Upvotes: 1

Jaap Mosselman
Jaap Mosselman

Reputation: 33

In case you use number instead of string as the enum values this would work:

enum Enum1 {
  Key1 = 2
}

enum Enum2 {
  Key1 = 2
}

const key = Enum1.Key1
const key2 = Enum2[Enum1[key]];

Upvotes: 1

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249706

At runtime the variable will contain the enum value (key in your case) So you can just cast through any and it should work

const key = Enum1.Key1
const key2: Enum2 = key as any

Upvotes: -1

Related Questions