Typescript React:如何覆盖默认的 html 输入元素属性props类型

IT技术 reactjs typescript
2021-05-20 17:14:14

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

但是,我也试图在我自己的接口定义中使用 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} />;
};

传输错误

(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)
2个回答

替换interface InputProps....

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

根据 OP 的评论,

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

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

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

但是在这样做之后,您需要在Input组件内部做一些事情来将您的自定义size字符串映射到数字,然后才能将它们传递给input.

编辑:

根据您的评论,您说过这些是 CSS 类名。所以它们需要传递给属性中input组件className,而不是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. 事实上,这个组件永远不能为 上的size属性设置任何东西,input因为我们在size使用扩展运算符 ( {size = 'md', className, ...props})时去掉了...props是“休息”参数,这意味着它具有所有的属性,否则不能提取,所以不会包含sizeclassNameInputProps