0%

Typescript动态类型推断

实现一个功能,根据第一个字段输入的值来动态更改其余字段的类型

比如如下代码

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'componentPropsInputProps,同理当为 '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;
}
// T是一个类型而keyof InputType是字符串,所以要用extends产生新类型
// 如果是 T = keyof InputType则会出现 Type 'T' cannot be used to index type 'InputType'.(2536) 错误
type FormItemDefinition<T extends keyof InputType> = {
type: T;
componentProps?: InputType[T];
}
// 最关键在这,定义一个数组,这个数组类型是 T extends keyof InputType ? FormItemDefinition<T> : any,如果T是InputType的其中一个最后类型就是 FormItemDefinition<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 限制对应类型的泛型,就是不同类型的集合了