Compare enum to enum of another type

Viewed 357

I'm having enums with identical values but different names:

enum EnumA{
  HELLO,
  WORLD
}
enum EnumB{
  HELLO,
  WORLD
}

As you they are bot generated by an external source an have the same values, but are used in an component where it can be EnumA or EnumB.

let x: EnumA | EnumB = EnumA.HELLO;
// or
let x: EnumA | EnumB = EnumB.HELLO;

If I wan to check for HELLO I need to

if(x === EnumA.HELLO || x === EnumB.HELLO)

Is there an easier way to do this check or tell typescript that these two enums are identical?

Something like:

const x: EnumA | EnumB = EnumB.HELLO;

if(x === EnumA.HELLO) {
    console.log('they are the same')
}

If I try this I get the typescript warning:

This condition will always return 'false' since the types 'EnumB.HELLO' and 'EnumA.HELLO' have no overlap.

But the console.log is called! Demo: https://www.typescriptlang.org/play/#code/KYOwrgtgBAouEEEDeBYAUFTUASMAyeA8gDTpZQDqhASngCLoC+6oks8AQqhlrgSWSxVaDNMzToAxgHsQAZwAuUAB4AudpARQAPhogcoAXj0cAdHyIBudOgCWAMwAUyo4eNxN5-EQCUUbuQy8tIANsCmIdIA5o4A5AoAFsAAnlAAhgBOwFCJ2XJpEMCxPkxAA

2 Answers

Union-type variables are narrowed by control-flow analysis upon assignment. That means the line

const x: EnumA | EnumB = EnumA.HELLO;

ends up narrowing the type of x all the way to type EnumA.HELLO, and it is considered an error to compare two unrelated types like EnumA.HELLO and EnumB.HELLO.

If you want to prevent this from happening so that x can be compared to both an EnumA and an EnumB you can use a type assertion like this:

const x = EnumB.HELLO as EnumA | EnumB;

Then the comparison will work:

if (x === EnumA.HELLO) { } // okay

Link to code


But if both EnumA and EnumB are generated by an external source and you know they will be identical, then it seems like a headache to allow them to appear as different types in the first place. I don't know enough about your code to suggest how to address this... only import EnumA and ignore EnumB? Merge EnumA and EnumB into a single object and only reference the combined EnumAB? Not sure.


Anyway, hope that helps. Good luck!

ok so this

const x: EnumA | EnumB = EnumB.HELLO;

if(x === EnumA.HELLO) {
    console.log('they are the same')
}

throw error since u are comparing const wich is EnumB.HELLO and ts can see this.

if u get the value from function like this

const a = (): EnumA | EnumB => {
  return EnumA.HELLO;
};
const x: EnumA | EnumB = a();

if (x === EnumB.HELLO) {
  console.log('they are the same');
}

that's correct and runtime will pass the condition since this is the same number

the other solution is to compare it like number.

const x: number = EnumA.HELLO;

if (x === EnumB.HELLO) {
  console.log('they are the same');
}

and again runtime will pass the condition since this is the same number...

Related