Typescript动态类型推断

作者:taikulawo创建时间:2020-10-12字数统计:2175预计阅读需要5分钟

#前端

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

比如如下代码

interface InputProps {
    label: string;
}
interface SelectProps {
    name: string;
}
export interface InputType {
    input: InputProps;
    select: SelectProps;
}
export type FormItemDefinition = {
    type: 'input' | 'select';
    componentProps?: any
}
<!--more-->

我希望当 type === 'input'componentPropsInputProps,同理当为 'select'componentProps'SelectProps'

初步实现我们的需求

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

componentProps?: InputProps | SelectProps | undefined

而目标是

componentProps?: InputProps | undefined

进一步优化

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 限制对应类型的泛型,就是不同类型的集合了

0 comments
Anonymous
Markdown is supported

Be the first guy leaving a comment!