kk-dev11
kk-dev11

Reputation: 2674

TypeScript: Generics check for enum type

There is an enum for process. They have different steps, which are also represented as enums as shown below.

enum Process {
  Simple = "simple",
  Advanced = "advanced"
}

enum SimpleStep {
  A = "A",
  B = "B"
}

enum AdvancedStep {
  A = "A",
  B = "B",
  C = "C"
}

With the following statements, I created an array of steps.

const SIMPLE_STEPS = Object.keys(SimpleStep).map(
  (k: string) => SimpleStep[k]
);

const ADVANCED_STEPS = Object.keys(AdvancedStep).map(
  k => AdvancedStep[k]
);

const ALL_STEPS = {
  [Process.Simple]: SIMPLE_STEPS,
  [Process.Advanced]: ADVANCED_STEPS
};

I wrote the following function to get the step number.

// ???: Check if S is a step of Process
const getStepNumber = <P extends Process, S>(process: P, step: S) => {
  return ALL_STEPS[process].indexOf(step) + 1;
};

// returns 2, which is correct
console.log('step number of B', getStepNumber(Process.Advanced, AdvancedStep.B)); 

// returns 0. Is it possible to prevent at compile-time?
console.log('step number of C', getStepNumber(Process.Simple, AdvancedStep.C));

As you can see in the code example, is it possible to prevent calling the function with wrong step during compile-time using generics?

Here is the playground, if you wish to try out the whole example: TS Playground

Upvotes: 0

Views: 3561

Answers (1)

Yoni Gibbs
Yoni Gibbs

Reputation: 7018

One option is to introduce a conditional type that will allow you to infer the require step enum (i.e. SimpleStep or AdvancedStep) based on the Process supplied to the function. This could be done as follows:

type StepFromProcess<P extends Process> =
    P extends Process.Simple ? SimpleStep : AdvancedStep

Then you could change your function to use that type:

const getStepNumber = <P extends Process>(process: P, step: StepFromProcess<P>) => ...

The compiler will now prevent you making this (invalid) call:

console.log('step number of C', getStepNumber(Process.Simple, AdvancedStep.C));

Upvotes: 4

Related Questions