【问题标题】:Typescript React: How to override default html input element attribute prop typesTypescript React:如何覆盖默认的 html 输入元素属性道具类型
【发布时间】:2021-01-24 05:21:44
【问题描述】:

我正在尝试创建一个自定义“输入”组件并扩展默认的 html 输入属性(道具)。

但是,我也尝试在我自己的接口定义中使用 Typescript 的 Omit 来覆盖默认的“大小”属性,但似乎无法使其正常工作。

(我也尝试过 Typescript 的 Pick/Exclude 和自定义 Override 类型,但得到相同的错误...)

我已经尝试过的类似主题:

import React from 'react';

type A = React.HTMLAttributes<HTMLInputElement>;

interface InputProps extends Omit<A, 'size'> {
  size?: 'sm' | 'md' | 'lg';
}

const Input = (props: InputProps) => {
  return <input {...props} />;
};

TS 错误

(property) JSX.IntrinsicElements.input: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
Type '{ size?: "sm" | "md" | "lg"; defaultChecked?: boolean; defaultValue?: string | number | readonly string[]; suppressContentEditableWarning?: boolean; ... 250 more ...; onTransitionEndCapture?: (event: TransitionEvent<...>) => void; }' is not assignable to type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
  Type '{ size?: "sm" | "md" | "lg"; defaultChecked?: boolean; defaultValue?: string | number | readonly string[]; suppressContentEditableWarning?: boolean; ... 250 more ...; onTransitionEndCapture?: (event: TransitionEvent<...>) => void; }' is not assignable to type 'InputHTMLAttributes<HTMLInputElement>'.
    Types of property 'size' are incompatible.
      Type 'string' is not assignable to type 'number'.
        Type 'string' is not assignable to type 'number'.ts(2322)

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    interface InputProps.... 替换为

    type InputProps = {
     size?: 'sm' | 'md' | 'lg';
    } & Omit<A, 'size'>;
    

    根据 OP 的评论,

    const Input = ({ size, ...props }: InputProps) => {
      // if(size) do something...
      return <input {...props} />;
    };
    

    【讨论】:

    • 嗯......即使有这个定义,错误仍然存​​在
    • @TrieuNomad 它可能抱怨与输入不匹配,因为您将所有道具直接传递到输入中。试试我的新建议。
    • 我最终选择了 但你的方式也有效。将接受此作为解决方案,因为它修复了 ts 错误。
    【解决方案2】:

    这里的设计缺陷不是您在自定义 Input 组件中接受的道具。即使您已经知道您的 size 属性与预期的 size 属性不同,您也将这些相同的道具传递给 HTML input 组件。这就是您在此处粘贴的错误所反映的内容。

    您确实需要按照@silent 的说明修复您的类型定义。

    但是在这样做之后,您需要在您的 Input 组件中执行一些操作,将您的自定义 size 字符串映射为数字,然后才能将它们传递给 input

    编辑:

    根据您的评论,您说这些是 CSS 类名称。所以需要将它们传递给className 属性中的input 组件,而不是size 属性。

    // sets default size to 'md' - you can change or remove this
    const Input = ({size = 'md', className, ...props}: InputProps) => {
        // combine with existing class names
        const newClass = className + ' ' + size; // could trim redundant spaces but don't need to
    
        return (
            <input 
                {...props} 
                className={newClass}
            />;
    };
    

    您无需将任何内容传递给size。事实上,这个组件永远无法对input 上的size 属性设置任何内容,因为我们在使用扩展运算符({size = 'md', className, ...props}) 时取出了size...props 是一个“rest”参数,这意味着它具有未提取的所有属性,因此它不会包括来自InputPropssizeclassName

    【讨论】:

    • 我真的不想将字符串映射到指定的数值,我只想应用 css 类。但是我确实明白你在说什么,我想我可以将 size={undefined} 传递给嵌套的 html 输入,从而消除错误。谢谢你的解释!
    • 那么在这种情况下,将它们传递给className 属性。
    猜你喜欢
    • 1970-01-01
    • 2017-08-22
    • 2020-09-16
    • 2019-05-09
    • 2020-06-07
    • 2019-12-27
    • 2021-05-11
    • 2020-11-05
    • 1970-01-01
    相关资源
    最近更新 更多