TypeScript:泛型检查枚举类型

时间:2019-08-25 21:15:38

标签: typescript generics typescript-typings typescript-generics

有一个过程枚举。它们具有不同的步骤,也用枚举表示,如下所示。

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

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

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

使用以下语句,我创建了一个步骤数组。

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
};

我编写了以下函数来获取步骤编号。

// ???: 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));

如代码示例所示,是否可以防止在使用泛型的编译期间以错误的步骤调用函数?

如果您想尝试整个示例,请在这里玩耍:TS Playground

1 个答案:

答案 0 :(得分:1)

一种选择是引入条件类型,该条件类型将允许您根据提供给函数的SimpleStep来推断require步骤枚举(即AdvancedStepProcess)。可以这样完成:

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

然后您可以更改功能以使用该类型:

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

编译器现在将阻止您进行此(无效)调用:

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