1

我正在尝试在反应和打字稿中创建一个可重用的多步向导组件。该向导需要通过反应上下文对象将某些值传递给它。该上下文对象的值必须遵循一般模式:

export interface WizardContextValues {
  currentStep: number;
  setStep: (stepState: number) => void;
  completedSteps: { [key: string]: boolean };
  setCompletedSteps: (state: { [key: string]: boolean }) => void;
  disabledSteps: { [key: string]: boolean };
}

你可以看到completedStepsand disabledSteps,我期待一个对象。但我想进一步限制这一点。假设对于一个特定的向导,我有一个步骤枚举:

export enum UploadWizardSteps {
  UPLOAD_FILE,
  GIVE_DETAILS,
  CONFIRMATION
}

我想真正做到WizardContextValues通用,这样它将步骤枚举作为参数。像这样的东西:

export interface WizardContextValues<Steps> {
  currentStep: number;
  setStep: (stepState: number) => void;
  completedSteps: { [key in Steps]: boolean };
  setCompletedSteps: (state: { [key in Steps]: boolean }) => void;
  disabledSteps: { [key in Steps]: boolean };
}

type UploadWizardContext = WizardContextValues<UploadWizardSteps>

尝试使用时出现错误key in Steps,说Type 'Steps' is not assignable to type 'string | number | symbol'. Type 'Steps' is not assignable to type 'symbol'

这是有道理的,因为在定义 generic 时interface WizardContextValues<Steps>,打字稿不知道它Steps是一个枚举,并且它的键可以使用key in操作符来引用。

显示问题的打字稿游乐场

如何创建这种泛型类型,使得 的某些属性UploadWizardContext必须是其键值为 的对象UploadWizardSteps

4

1 回答 1

1

按照目前的编写方式,TypeScript 无法知道Steps它何时在内部使用WizardContextValues。您大概可以将其中的任何内容作为类型传递,包括不能用作键的内容。

您可以通过限制可用于Stepsusing的类型来解决此问题extends

默认情况下,TypeScript 枚举使用number值,尽管您可以使用更广泛的string | number | symbol类型来充分反映可用于对象属性的内容:

export enum UploadWizardSteps {
  UPLOAD_FILE,
  GIVE_DETAILS,
  CONFIRMATION
}

export interface WizardContextValues<Steps extends string | number | symbol> {
  currentStep: number;
  setStep: (stepState: number) => void;
  completedSteps: { [key in Steps]: boolean };
  setCompletedSteps: (state: { [key in Steps]: boolean }) => void;
  disabledSteps: { [key in Steps]: boolean };
}

type UploadWizardContext = WizardContextValues<UploadWizardSteps>

TypeScript 游乐场

于 2021-10-21T00:44:10.413 回答