TypeScript 泛型 - 期望类型参数是枚举,并引用它的键
TypeScript generics - expect type argument to be enum, and refer to its keys
我正在尝试在 React 和 Typecript 中创建一个可重用的多步向导组件。该向导将需要通过反应上下文对象将某些值传递给它。该上下文对象的值必须遵循一般模式:
export interface WizardContextValues {
currentStep: number;
setStep: (stepState: number) => void;
completedSteps: { [key: string]: boolean };
setCompletedSteps: (state: { [key: string]: boolean }) => void;
disabledSteps: { [key: string]: boolean };
}
您可以看到 completedSteps
和 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'
这种是有道理的,因为在定义泛型 interface WizardContextValues<Steps>
时,typescript 不知道 Steps
是一个枚举并且可以使用 key in
运算符引用它的键.
typescript playground showing the issue
如何创建此泛型类型,使 UploadWizardContext
的某些属性必须是其键值为 UploadWizardSteps
的对象?
按照目前的编写方式,TypeScript 在 WizardContextValues
中使用时无法知道有关 Steps
的任何信息。您大概可以将其中的任何内容作为类型传递,包括不能用作键的内容。
您可以通过使用 extends
.
限制可用于 Steps
的类型来解决此问题
默认情况下,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>
我正在尝试在 React 和 Typecript 中创建一个可重用的多步向导组件。该向导将需要通过反应上下文对象将某些值传递给它。该上下文对象的值必须遵循一般模式:
export interface WizardContextValues {
currentStep: number;
setStep: (stepState: number) => void;
completedSteps: { [key: string]: boolean };
setCompletedSteps: (state: { [key: string]: boolean }) => void;
disabledSteps: { [key: string]: boolean };
}
您可以看到 completedSteps
和 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'
这种是有道理的,因为在定义泛型 interface WizardContextValues<Steps>
时,typescript 不知道 Steps
是一个枚举并且可以使用 key in
运算符引用它的键.
typescript playground showing the issue
如何创建此泛型类型,使 UploadWizardContext
的某些属性必须是其键值为 UploadWizardSteps
的对象?
按照目前的编写方式,TypeScript 在 WizardContextValues
中使用时无法知道有关 Steps
的任何信息。您大概可以将其中的任何内容作为类型传递,包括不能用作键的内容。
您可以通过使用 extends
.
Steps
的类型来解决此问题
默认情况下,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>