Typescript how to safely cast an enum to another?

Viewed 230

I have 2 identical enums

enum State {
    On,
    Off,
}

enum Status {
    On,
    Off,
}

I would like to be able to affect a state value to the status one

const stateOn: State = State.On;
const statusOn1: Status = stateOn; // But we cannot because State !== Status

So trying to cast it will give the following:

const statusOn2: Status = stateOn as Status; // Error, cannot cast a State to a Status

const statusOn3: Status = stateOn as unknown as Status; // Okay but risky

Therefore would it be possible to create a conditional type which would ensure both enums are the same ?

Something like :

type castEnum<T, U> = Extract<keyof typeof T, keyof typeof U> extends keyof typeof U ? U : never;

To then be able to affect the variable like (idea):

const statusOn4: Status = stateOn as castEnum<State, Status>;
1 Answers

As I understand you want to have the same two enums only because of domain naming, so the important thing is to have two different names for the same structure. Then if my assumption is correct, the solution is not to create second enum but just create a type alias by type keyword:

type Status = State;

Now Status is the same type as State, but you can use both type names.

If you need to keep those two enums (quite a rare situation), then probably the solution would be to use union type which will be just one thing (as both those types are represented as 0 | 1 under the hood). State | Status === State === Status === 0 | 1. So the union of those type is really the same thing as one of them, as they are equal in representation.

Example using structures in both types.

const isOn = (s: State | Status) => {
  return s === Status.On // Status.On === 0 === State.On
}

const isOff = (s: State | Status) => {
   return s === Status.Off // Status.Off === 1 === State.Off
}

const a: State = State.On;
isOn(a) // true

const b: Status = Status.On;
isOn(b) // true


Related