TypeScript中React高阶组件(HoC)注入属性的类型定义问题
问题根源
当前类型报错的核心原因是高阶组件的泛型定义没有正确描述「注入属性」和「外部传入属性」的区分:
- HOC没有声明自身会向被包裹组件注入哪些属性,TS无法识别注入的
someState类型 - HOC返回的包装组件没有把注入属性从外部入参要求中剔除,导致要么内部访问报错,要么外部调用被强制要求传入注入属性
- 原代码还存在几处语法错误:
interfae拼写错误、箭头函数返回值写法错误、JSX展开props语法错误。
正确实现方案
第一步:定义HOC注入属性的公共类型
先抽离HOC统一注入的属性类型,方便所有被包裹组件复用:
interface HOCInjectedProps { // 替换为someState的实际类型,不要用any,比如如果是boolean就写boolean someState: unknown; }
第二步:修正HOC的泛型类型定义
调整HOC的泛型约束,明确区分「HOC内部注入的属性」和「需要外部传入的属性」:
import React, { useState, ComponentType } from 'react'; const HOC = <P extends HOCInjectedProps>(Component: ComponentType<P>) => { // 返回的包装组件只要求传入 被包裹组件需要的属性 排除掉HOC自己注入的部分 const WrappedComponent = (props: Omit<P, keyof HOCInjectedProps>) => { const [someState, setSomeState] = useState<HOCInjectedProps['someState']>(); // 合并外部传入props和HOC内部状态,传给被包裹组件 return <Component {...(props as P)} someState={someState} />; }; return WrappedComponent; };
第三步:定义被包裹组件的Props类型
被包裹组件内部需要同时访问自有属性和HOC注入属性,用交叉类型合并即可,不需要担心外部调用被要求传注入属性:
// 只定义组件自身需要外部传入的属性 interface NewComponentProps { x: number; } // 组件内部props类型 = 自有属性 + HOC注入属性 const NewComponent = (props: NewComponentProps & HOCInjectedProps) => { // 这里可以正常解构x和someState,不会报TS类型错误 const { x, someState } = props; return <div>{x} - {String(someState)}</div>; }; // 包裹后导出,外部调用时只需要传入x属性,不需要传someState export default HOC(NewComponent);
类型逻辑说明
- 泛型约束
P extends HOCInjectedProps要求传入HOC的组件必须能够接收someState属性,从源头避免组件漏写注入属性的类型 Omit<P, keyof HOCInjectedProps>表示从组件要求的总属性P中,剔除掉HOC会自己注入的部分,这部分不需要外部传入,因此外部调用导出的组件时,TS只会校验组件自身的属性(比如示例中的x)- 被包裹组件用交叉类型合并自有属性和注入属性,内部访问属性时TS可以正常推导类型,不会报错
内容的提问来源于stack exchange,提问作者lazyCoder
相关产品推荐
相关产品推荐

