Typescript React: 如何覆盖默认的HTML输入元素属性prop类型
Typescript React: 如何覆盖默认的HTML输入元素属性prop类型
我正在尝试创建一个自定义的"Input"组件,并扩展默认的HTML输入属性(props)。
然而,我还尝试使用Typescript的Omit在自己的接口定义中覆盖默认的'size'属性,但似乎无法使其工作。
(我还尝试了Typescript的Pick/Exclude和自定义的Override类型,但得到相同的错误...)
我已经尝试过的类似主题:
- Override the properties of an interface in TypeScript
- How extend React types to support html attributes as props
import React from 'react'; type A = React.HTMLAttributes; interface InputProps extends Omit { size?: 'sm' | 'md' | 'lg'; } const Input = (props: InputProps) => { return ; };
TS Error
(property) JSX.IntrinsicElements.input: React.DetailedHTMLProps, 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 , 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 '. Types of property 'size' are incompatible. Type 'string' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'.ts(2322)
在这里的设计缺陷不是你在自定义的Input
组件中接受的props,而是你将这些相同的props传递给HTML的input
组件,尽管你已经知道你的size
属性与预期的size
属性不同。这就是你贴出的错误所反映的问题。
你确实需要根据...props
的解释来修复你的类型定义。但在这之后,你需要在Input
组件内部做一些工作,将你的自定义size
字符串映射为数字,然后才能将它们传递给input
组件。
根据你的评论,你说这些是CSS类名。所以它们需要通过className
属性传递给input
组件,而不是size
属性。
所以在这种情况下,将它们传递给className
属性即可。
// 设置默认的size为'md' - 你可以更改或删除这个 const Input = ({size = 'md', className, ...props}: InputProps) => { // 将现有的类名与新的类名组合在一起 const newClass = className + ' ' + size; // 可以修剪多余的空格,但不需要 return ( ; };
你不需要将任何内容传递给size
。实际上,这个组件永远不能将任何内容设置给input
的size
属性,因为当我们使用扩展运算符({size = 'md', className, ...props}
)时,我们将size
排除在外。...props
是一个"rest"参数,意味着它包含了所有未被提取的属性,所以它不会包含来自InputProps
的size
或className
。
我真的不想将字符串映射为指定的数字值,我只想应用CSS类。不过我理解你的意思,我想我可以将size={undefined}
传递给嵌套的HTML input,这样就可以消除错误了。谢谢你的解释!
那么在这种情况下,将它们传递给className
属性即可。
问题的出现原因是在使用Typescript和React开发过程中,尝试覆盖默认的HTML输入元素属性的属性类型时出现了错误。解决方法是替换原先的接口定义为一个类型定义,并使用Omit类型将原先的属性类型中的'size'属性排除掉。
具体的解决方法如下所示:
type InputProps = { size?: 'sm' | 'md' | 'lg'; } & Omit;
然后,在Input组件中使用这个新定义的InputProps类型,并将除了'size'属性之外的所有属性传递给input元素。
const Input = ({ size, ...props }: InputProps) => { // 如果有size属性,做一些操作... return ; };
尽管使用了这个新的定义,但是问题仍然存在。可能是因为直接将所有属性传递给input元素导致了类型不匹配的错误。尝试使用以下方法:
或者也可以尝试将这个新的解决方法应用到其他文件中导出的InputProps类型中。
总结一下,问题的原因可能是即使没有直接将size属性传递给input元素,仍然会出现相同的错误。而解决方法是使用Omit类型将原先的属性类型中的'size'属性排除掉,并将除了'size'属性之外的所有属性传递给input元素。
问题的出现原因是需要在React中覆盖默认的HTML输入元素的属性类型。解决方法如下:
首先,我们不需要替换接口,而是可以通过扩展现有接口来实现。将InputProps接口扩展为除了size属性之外的所有类型A的属性,并添加一个可选的size属性。
接下来,定义类型A为React.InputHTMLAttributes的详细属性类型。这样可以获得HTMLInputElement的所有属性类型。
然后,定义InputSize为'xs'、'sm'、'md'、'lg'中的一个字符串字面量类型。
最后,定义Input组件,接受InputProps作为参数。在组件内部,我们可以通过解构赋值获取style、className和size属性,并将剩余的属性赋值给rest变量。注意,我们不需要为size属性传递默认值。
最终,将rest属性传递给input元素,并返回它。
通过上述方法,我们可以在React中覆盖默认的HTML输入元素的属性类型。