React TypeScript可复用Input组件size参数冲突报错求解决
修复React TypeScript Input组件size参数冲突问题
问题原因
你定义的自定义size参数(类型为's'|'m')和原生<input>标签的size属性(类型为number | undefined)发生了冲突。当两个类型交叉时,因为没有共同的取值范围,最终size的类型被推断为never,导致TypeScript抛出TS2322错误。
解决方案
方案1:重命名自定义size参数
把自定义的size改成其他名称(比如inputSize),避免和原生属性重名:
import React, { forwardRef } from 'react'; import classNames from 'classnames'; // 修改类型定义,将size改为inputSize type IInputProps = { name?: string; inputSize?: 's' | 'm'; // 重命名参数 status?: '' | 'disabled' | 'invalid'; } & React.ComponentPropsWithRef<'input'>; const Input = forwardRef<HTMLInputElement, IInputProps>( ({ name, inputSize = 'm', status = '', ...rest }: IInputProps, ref) => { const inputClassNames = classNames( 'text-dark w-full ring-2 rounded-full py-1.5 px-3 tracking-wider dark:bg-bright', { 'ring-transparent hover:ring-cyan hover:dark:ring-bright/10 focus-within:outline-none focus-within:border-none focus:ring-cyan': status !== 'invalid', 'ring-transparent border-1 border-amber-600 focus-within:outline-none ': status === 'invalid', 'h-12': inputSize === 'm', // 对应修改引用 'text-sm h-10': inputSize === 's', // 对应修改引用 'opacity-50': status === 'disabled', }, ); return ( <div className='w-full'> <input ref={ref} id={name} name={name} className={inputClassNames} {...rest} /> </div> ); }, ); Input.displayName = 'Input'; export default Input;
方案2:剔除原生input的size属性
从React.ComponentPropsWithRef<'input'>中移除原生的size属性,保留自定义的size:
import React, { forwardRef } from 'react'; import classNames from 'classnames'; // 使用Omit剔除原生size属性 type IInputProps = { name?: string; size?: 's' | 'm'; status?: '' | 'disabled' | 'invalid'; } & Omit<React.ComponentPropsWithRef<'input'>, 'size'>; // 剔除原生size const Input = forwardRef<HTMLInputElement, IInputProps>( ({ name, size = 'm', status = '', ...rest }: IInputProps, ref) => { const inputClassNames = classNames( 'text-dark w-full ring-2 rounded-full py-1.5 px-3 tracking-wider dark:bg-bright', { 'ring-transparent hover:ring-cyan hover:dark:ring-bright/10 focus-within:outline-none focus-within:border-none focus:ring-cyan': status !== 'invalid', 'ring-transparent border-1 border-amber-600 focus-within:outline-none ': status === 'invalid', 'h-12': size === 'm', 'text-sm h-10': size === 's', 'opacity-50': status === 'disabled', }, ); return ( <div className='w-full'> <input ref={ref} id={name} name={name} className={inputClassNames} {...rest} /> </div> ); }, ); Input.displayName = 'Input'; export default Input;
两种方案都能解决冲突,方案1更直观,避免后续混淆;方案2保留了自定义参数的命名,适合希望保持API语义一致性的场景。
内容的提问来源于stack exchange,提问作者strangeQuirks
相关产品推荐
相关产品推荐

