React+TypeScript实现全静态类型HOC 隐藏注入name属性的类型要求
需求可实现,你之前的报错核心是两个问题:
- 剔除注入属性的类型逻辑错误,你定义的
WithoutAAdds并没有从原组件Props中排除name属性 - 未处理React
FC类型默认携带的隐式类型约束,导致泛型兼容报错
修正后的完整实现代码
import { FC, PropsWithChildren } from 'react' type AAdds = { name: string } type WithAAdds<T> = T & Partial<AAdds> // 从原组件Props中剔除所有已被HOC注入的属性 type OmitInjectedProps<P> = Omit<P, keyof AAdds> const withMyHoc = function<P extends object>(Wrapped: FC<WithAAdds<P>>) { return (props: PropsWithChildren<OmitInjectedProps<P>>) => { // 类型断言安全:已通过Omit确保props为P中除注入属性外的全部内容 return <Wrapped name="john" {...props as P} /> } as FC<OmitInjectedProps<P>> } // 业务组件无需改动 const MyComponent = ({name, lastName}: {name:string, lastName: string}) => { return ( <div> {name} : {lastName} </div> ) } const MyHocComponent = withMyHoc(MyComponent) const App = () => { // 现在仅需传入lastName,类型提示不会展示name属性,无类型报错 return <MyHocComponent lastName="Doe" /> }
关键调整说明
- 给泛型
P增加extends object约束,避免TS认为P可能是和Props完全无关的任意类型 - 修正属性剔除逻辑:用
Omit<P, keyof AAdds>直接从原组件Props中去掉所有已被注入的属性,得到外部调用时需要传入的属性集合 - 用
PropsWithChildren包裹返回组件的Props,兼容React 18之前FC类型默认携带的children属性约束(如果是React 18+且不需要支持隐式children,可去掉该包裹) - 对传入内部组件的props做安全类型断言,避免TS无法识别属性合并后的类型匹配关系
效果验证
最终得到的MyHocComponent的类型提示只会展示需要传入的lastName属性,不会出现name,同时所有属性都有完整的静态类型校验,符合需求。
内容的提问来源于stack exchange,提问作者Jackson
相关产品推荐
相关产品推荐

