'How to check two enum has same value, or typesafe way to use both?

I have two typescript enum that values are same.

enum A{
  ONE: "ONE",
  TWO: "TWO",
}
enum B{
  ONE: "ONE",
  TWO: "TWO",
}

And value is type of enum A and function's parameter is enum B type. I want to give A to function parameter. I know that I can acheive this with type casting.

(param as unknown) as B // param is enum A

But I want to avoid type casting and unknown conversion as much as possible. How can I do it?



Solution 1:[1]

You could change the type of the argument of the function that uses the enum value:

function useEnum(enumValue: `${A}`) {}

It now accepts any string value that matches the values of the A enum.

// works fine
useEnum(A.ONE)
useEnum(A.TWO)
useEnum(B.ONE)
useEnum(B.TWO)

If B has any additional values that A does not have, they would not be accepted as arguments.

enum B {
  ONE = "ONE",
  TWO = "TWO",
  THREE = "THREE"
}

// error: Argument of type 'B.THREE' is not assignable to parameter of type '"ONE" | "TWO"'.
useEnum(B.THREE)

Playground


Keep in mind that this breaks if the enums are using numbers instead of strings.

enum A {
  ONE,
  TWO
}

function useEnum(enumValue: `${A}`) {}

// Argument of type 'A.ONE' is not assignable to parameter of type '"0" | "1"'
useEnum(A.ONE)

This can be fixed by adding a generic type T to the function.

enum A {
  ONE = "ONE",
  TWO = 2
}

enum B {
  ONE = "ONE",
  TWO = 2,
  THREE = "THREE"
}

type IsAValue<T extends string | number> =
  `${T}` extends `${A}` ? T : A

function useEnum<T extends string | number>(enumValue: IsAValue<T>) {}

// works fine
useEnum(A.ONE)
useEnum(A.TWO)
useEnum(B.ONE)
useEnum(B.TWO)

// error: Argument of type 'B.THREE' is not assignable to parameter of type 'A'
useEnum(B.THREE)

Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1