【问题标题】:How to write generic typings for HOC with typescript?如何使用打字稿为 HOC 编写通用类型?
【发布时间】:2019-07-28 12:44:42
【问题描述】:

我正在为现有 UI 库编写类型,该库具有一个 Base 组件,该组件将 Element 作为字符串并执行 <Element {...props} 正确的输入方式是什么?

我尝试用

编写泛型类型
type AllTypes = HTMLProps<HTMLDivElement> | HTMLProps<HTMLInputElement> // ... And other HTML element types
type BaseTypes <T extends AllTypes> = {
    Element: string;
    props: T;
    className?: string;
    baseClassName?: string;
}


export const BaseComponent = <T extends AllTypes>({
    Element = "div",
    baseClassName,
    className,
    ...props
}: BaseTypes<T> ) => {
    const classNames = [];

    if (baseClassName) {
        classNames.push(baseClassName);
    }
    if (className) {
        classNames.push(className);
    }



    return (
        <Element 
            className={classNames.join(' ')}
            {...props }
        />
    )
}

另一边

type newType = {
    Element: string;
    props: HTMLProps<HTMLInputElement>,
    className?: string;
    baseClassName?:string;
}

const InputField = (props: newType): ReactElement => {
    return (
        <BaseComponent<HTMLProps<HTMLInputElement>>
            Element="input"
            baseClassName="ff-input"
            {...props}
        />
    );
};

export default InputField;

我遇到了一些错误,例如无法将 {className:string} 分配给 IntrinsicAttributes。

我想知道键入 BaseComponent 的正确方法,以便根据 Element 值确定道具类型。任何建议将不胜感激。

【问题讨论】:

    标签: reactjs typescript typescript-generics


    【解决方案1】:

    你不能在 JSX 中只使用一个纯字符串作为 Element。如果你想使用一个字符串,你可以换成这样做......

    React.createElement(Element, { ...props, className: classNames.join(' ') }, null);
    

    或者您可以将元素的类型修改为ElementType&lt;any&gt;,例如...

    import * as React from 'react';
    import { HTMLProps, ReactElement, ElementType } from 'react';
    
    export type BaseProps = {
        Element: ElementType<any>;
        className?: string;
        baseClassName?: string;
    }
    
    export const BaseComponent = <T extends {}>({
        Element = "div",
        baseClassName,
        className,
        ...props
    }: T & BaseProps) => {
        const classNames = [];
    
        if (baseClassName) {
            classNames.push(baseClassName);
        }
        if (className) {
            classNames.push(className);
        }
    
        return <Element { ...{...props, className: classNames.join(' ') } } />;
    }
    
    const InputField = (props: HTMLProps<HTMLInputElement>): ReactElement => {
        return (
            <BaseComponent<HTMLProps<HTMLInputElement>>
                Element="input"
                baseClassName="ff-input"
                {...props}
            />
        );
    };
    
    export default InputField;
    

    【讨论】:

    • 感谢您的帮助!我确实进行了一些修改以使其正常工作。但这种方法绝对有效。我让它在没有双扩展运算符的情况下工作。
    猜你喜欢
    • 2019-08-10
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2018-06-26
    • 1970-01-01
    • 2021-01-27
    • 2018-04-16
    相关资源
    最近更新 更多