通用反应组件道具
Generic react component props
我正在使用带有 'fieldStructures' 和 'onSubmit' 属性的打字稿在 React 中构建一个表单组件。
type FieldStructure {
type: 'text';
name: string;
label?: string;
helpText?: string;
required?: boolean;
multiline?: boolean;
} | {
type: 'date';
name: string;
label?: string;
helpText?: string;
required?: boolean;
} | {
type: 'option';
name: string;
label?: string;
helpText?: string;
required?: boolean;
options: string[];
multi?: boolean;
} | {
type: 'file';
name: string;
label?: string;
helpText?: string;
required?: boolean;
fileTypes?: string[];
}
type FieldValue <T extends FieldType = any> =
T extends 'text' ? string
: T extends 'date' ? Date | null
: T extends 'option' ? string | string[] | null
: T extends 'file' ? string | File | null
: string | string[] | Date | File | null
interface FormModalProps {
fieldStructures: FieldStructure[];
handleSubmit: (values: { [key: string]: FieldValue }) => void | Promise<void>;
}
export const FormModal: React.FC<FormModalProps> = ({
fieldStructures,
handleSubmit
}) => { ... }
这对于制作组件非常有用,但对于使用它却不是那么有用。我希望 values 参数的类型依赖于像这样传递给 fieldStructures 参数的内容...
interface FormValues <T extends FieldStructure[]> {
//keys are the names of each field structure
//values are FieldValue<field structure type>
}
interface FormModalProps <T extends FieldStructure[]> {
fieldStructures: T;
handleSubmit: (values: FormValues<T>) => void | Promise<void>;
}
这个例子感觉过于简单了,但有谁知道实现相同结果的方法吗?
完整代码可在我的 github 上找到:
https://github.com/baldwin-design-co/bdc-components/blob/master/src/form%20modal/form-modal.tsx
你应该为每个结构指定一个类型,它扩展了一个指定的 属性 的通用类型(在你的例子中,type
)。
然后对于每个表单,您还需要接收一个扩展通用配置的配置。 FormValue 将是一个简单的 keyof T
.
检查下面这个例子:
// Field types
export interface FieldStructure {
type: 'text' | 'date';
}
export interface TextField extends FieldStructure {
type: 'text';
label: string;
}
export interface DateField extends FieldStructure {
type: 'date';
label: string;
}
// Calculate the value based on field type
export type FieldValue<T extends FieldStructure> =
T extends TextField ? string
: T extends DateField ? Date | null
: string | Date | null ;
// Types the form itself
type FormConfig = {[key: string]: FieldStructure}
// Gets the form value based on the type of each field
type FormValue<T extends FormConfig> = {
[k in keyof T]: FieldValue<T[k]>
}
// Example of usage:
interface MyFormConfig extends FormConfig {
a: TextField;
b: DateField
}
我正在使用带有 'fieldStructures' 和 'onSubmit' 属性的打字稿在 React 中构建一个表单组件。
type FieldStructure {
type: 'text';
name: string;
label?: string;
helpText?: string;
required?: boolean;
multiline?: boolean;
} | {
type: 'date';
name: string;
label?: string;
helpText?: string;
required?: boolean;
} | {
type: 'option';
name: string;
label?: string;
helpText?: string;
required?: boolean;
options: string[];
multi?: boolean;
} | {
type: 'file';
name: string;
label?: string;
helpText?: string;
required?: boolean;
fileTypes?: string[];
}
type FieldValue <T extends FieldType = any> =
T extends 'text' ? string
: T extends 'date' ? Date | null
: T extends 'option' ? string | string[] | null
: T extends 'file' ? string | File | null
: string | string[] | Date | File | null
interface FormModalProps {
fieldStructures: FieldStructure[];
handleSubmit: (values: { [key: string]: FieldValue }) => void | Promise<void>;
}
export const FormModal: React.FC<FormModalProps> = ({
fieldStructures,
handleSubmit
}) => { ... }
这对于制作组件非常有用,但对于使用它却不是那么有用。我希望 values 参数的类型依赖于像这样传递给 fieldStructures 参数的内容...
interface FormValues <T extends FieldStructure[]> {
//keys are the names of each field structure
//values are FieldValue<field structure type>
}
interface FormModalProps <T extends FieldStructure[]> {
fieldStructures: T;
handleSubmit: (values: FormValues<T>) => void | Promise<void>;
}
这个例子感觉过于简单了,但有谁知道实现相同结果的方法吗?
完整代码可在我的 github 上找到: https://github.com/baldwin-design-co/bdc-components/blob/master/src/form%20modal/form-modal.tsx
你应该为每个结构指定一个类型,它扩展了一个指定的 属性 的通用类型(在你的例子中,type
)。
然后对于每个表单,您还需要接收一个扩展通用配置的配置。 FormValue 将是一个简单的 keyof T
.
检查下面这个例子:
// Field types
export interface FieldStructure {
type: 'text' | 'date';
}
export interface TextField extends FieldStructure {
type: 'text';
label: string;
}
export interface DateField extends FieldStructure {
type: 'date';
label: string;
}
// Calculate the value based on field type
export type FieldValue<T extends FieldStructure> =
T extends TextField ? string
: T extends DateField ? Date | null
: string | Date | null ;
// Types the form itself
type FormConfig = {[key: string]: FieldStructure}
// Gets the form value based on the type of each field
type FormValue<T extends FormConfig> = {
[k in keyof T]: FieldValue<T[k]>
}
// Example of usage:
interface MyFormConfig extends FormConfig {
a: TextField;
b: DateField
}