实现一个功能,根据第一个字段输入的值来动态更改其余字段的类型
比如如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| interface InputProps { label: string; } interface SelectProps { name: string; } export interface InputType { input: InputProps; select: SelectProps; } export type FormItemDefinition = { type: 'input' | 'select'; componentProps?: any }
|
我希望当 type === 'input'
时 componentProps
为 InputProps
,同理当为 'select'
时 componentProps
为 'SelectProps'
初步实现我们的需求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| type InputProps = { label: string; } type SelectProps = { name: string; } export type InputType = { input: InputProps; select: SelectProps; } type FormItemDefinition<T extends keyof InputType = keyof InputType> = { type: T; componentProps?: InputType[T]; } const a: FormItemDefinition = { type: 'input', componentProps: { } } export const ItemCreateList: FormItemDefinition[] = [ { type: 'input', componentProps: { } } ]
|
上述代码有个问题,componentProps包含了全部的类型
具体看这个Playground
1
| componentProps?: InputProps | SelectProps | undefined
|
而目标是
1
| componentProps?: InputProps | undefined
|
进一步优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| type InputProps = { label: string; } type SelectProps = { name: string; } export type InputType = { input: InputProps; select: SelectProps; }
type FormItemDefinition<T extends keyof InputType> = { type: T; componentProps?: InputType[T]; }
export type FormItems<T = keyof InputType> = (T extends keyof InputType ? FormItemDefinition<T> : any)[]
export const ItemCreateList: FormItems = [ { type: 'input', componentProps: { label:'' }, }, { type: 'select', componentProps: { name: '' }, }, ];
|
以上代码可以在这里找到
FormItemDefinition
不能设置联合类型的默认值,要不然 componentProps
也都是联合类型了,就无法区分了,把默认值提取出去,然后逐个给 FormItemDefinition
限制对应类型的泛型,就是不同类型的集合了