React+TypeScript中泛型extends未强制校验组件属性问题
问题原因
问题1:传入不满足props要求的Component不报错
你当前的泛型写法下,TypeScript 会优先从传入的component参数反向推断泛型ComponentProps的实际类型,再校验是否符合约束。而 React 组件类型ComponentType<P>的参数P处于逆变位置:只要传入的组件接收的属性是ComponentProps的子集,TypeScript 就会认为类型兼容(组件忽略额外传入的onBlur属性不属于类型错误),所以即使传入的组件没有定义onBlur属性,也不会触发约束校验。
问题2:内部渲染Component时报错
这是 TypeScript 4.4 版本的泛型推断限制:你手动拼接的rest+onChange+onBlur属性,TypeScript 无法自动识别为完整的ComponentProps类型,会误判属性不完整。
解决方案
调整泛型的定义顺序,先从传入的component提取属性类型P,再直接约束P必须包含onChange和onBlur,解决逆变导致的校验失效问题;内部渲染时对拼接后的属性做一次类型断言,解决泛型推断限制导致的误报。
修复后完整代码
import React from 'react'; function Component({ onChange, }: { onChange: (event: React.ChangeEvent) => void; }) { return <input onChange={onChange} />; } // 调整泛型顺序:先获取组件Props类型P,再约束P必须包含onChange和onBlur function Field< P extends { onChange: (event: React.ChangeEvent) => void; onBlur: (event: React.FocusEvent) => void; } >({ component: Component, ...rest }: { component: React.ComponentType<P>; } & Omit<P, "onChange" | "onBlur">) { // 拼接属性后断言为P类型,解决TS泛型推断误报 const componentProps = { ...rest, onChange: (event: React.ChangeEvent) => {/* 业务逻辑 */}, onBlur: (event: React.FocusEvent) => {/* 业务逻辑 */}, } as P; return <Component {...componentProps} />; } export function App() { // 现在这里会正确报错:Component的props缺少必选属性onBlur return <Field component={Component} />; }
内容的提问来源于stack exchange,提问作者MarTic
相关产品推荐
相关产品推荐

