Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript动态类型推断 #51

Open
taikulawo opened this issue Oct 12, 2020 · 0 comments
Open

Typescript动态类型推断 #51

taikulawo opened this issue Oct 12, 2020 · 0 comments
Labels

Comments

@taikulawo
Copy link
Collaborator

taikulawo commented Oct 12, 2020

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

比如如下代码

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'

初步实现我们的需求

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant