如何根据布尔值isTextArea正确定义React组件类型?
如何为Input组件正确区分input和textarea的Props类型?
我尝试通过布尔值isTextArea为Input组件区分input和textarea的Props类型,但出现类型错误,请问该如何正确定义对应类型?
我的代码如下:
type InputProps = | ({ isTextArea: false; label: string; } & React.ComponentPropsWithoutRef<'input'>) | ({ isTextArea: true; label: string; } & React.ComponentPropsWithoutRef<'textarea'>); const Input: React.FC<InputProps> = ({ isTextArea, label, ...props }) => { return ( <div className='w-full'> <label htmlFor=''></label> {isTextArea ? <textarea {...props} /> : <input {...props} />} </div> ); }; export default Input;
问题原因
提前解构props后,TypeScript无法再通过isTextArea这个判别式缩小props的类型——解构后的props会被推断为input和textarea所有属性的交集,而两者存在不兼容属性(比如rows为textarea独有、type为input独有),因此会触发类型不匹配错误。
修复方案
方案一:保留完整props对象进行类型缩小
不要提前解构props,直接在条件分支中使用完整的props对象,让TypeScript通过isTextArea自动识别对应类型:
type InputProps = | ({ isTextArea: false; label: string; } & React.ComponentPropsWithoutRef<'input'>) | ({ isTextArea: true; label: string; } & React.ComponentPropsWithoutRef<'textarea'>); const Input: React.FC<InputProps> = (props) => { const { isTextArea, label } = props; return ( <div className='w-full'> <label htmlFor=''></label> {isTextArea ? <textarea {...props} /> : <input {...props} />} </div> ); }; export default Input;
方案二:解构后用类型断言明确属性类型
如果需要避免把isTextArea和label传递给原生元素,可以解构后对剩余属性做类型断言:
type InputProps = | ({ isTextArea: false; label: string; } & React.ComponentPropsWithoutRef<'input'>) | ({ isTextArea: true; label: string; } & React.ComponentPropsWithoutRef<'textarea'>); const Input: React.FC<InputProps> = (props) => { const { isTextArea, label, ...rest } = props; return ( <div className='w-full'> <label htmlFor=''></label> {isTextArea ? ( <textarea {...(rest as React.ComponentPropsWithoutRef<'textarea'>)} /> ) : ( <input {...(rest as React.ComponentPropsWithoutRef<'input'>)} /> )} </div> ); }; export default Input;
方案一更简洁安全,TypeScript能完整识别分支中的props类型;方案二适合需要单独处理多余属性的场景。
内容的提问来源于stack exchange,提问作者Mateusz Dariusz Szymczyk
相关产品推荐
相关产品推荐

