如何在Flow中为支持defaultProps的Props注入高阶组件正确类型标注(禁用*类型)
解决Flow中结合Redux注入Props与无废弃
*类型的HOC标注问题 问题分析
你的代码核心问题在于泛型约束和返回类型的匹配逻辑存在模糊性:
- 原代码里
Com: ComponentType<Props>的泛型Props和ElementConfig<Com>没有明确的关联关系,Flow无法正确推导组件接收的props与注入props的依赖逻辑 - 废弃的
*类型本质是让Flow跳过严格类型检查,所以错误会暂时消失,但这显然不是合规的长期方案
正确的类型标注方案
我们需要明确HOC的输入输出逻辑:传入的组件需要同时接收自定义Props和Redux注入的Props,返回的组件只需要接收自定义Props(注入Props由Redux自动补充)。以下是修正后的代码:
import React, { type ComponentType } from 'react'; import { connect } from 'react-redux'; import type { State } from 'client/types/redux'; export type InjectedProps = { xs: string[] }; // 泛型P代表组件自身需要的props(不包含Redux注入的InjectedProps) export default function injector<P>( DecoratedComponent: ComponentType<P & InjectedProps> ): ComponentType<P> { // 简化中间组件为函数式,减少类型复杂度 const Decorator = (props: P) => { return <DecoratedComponent {...props} />; }; // 明确标注mapStateToProps的返回类型,帮助Flow精准推导注入的props类型 return connect((state: State): InjectedProps => ({ xs: state.xs, }))(Decorator); }
代码细节解释
- 泛型定义:
P指代使用该HOC的组件自身需要的props,传入的DecoratedComponent需要同时兼容P和InjectedProps(因为Redux会自动注入后者) - 返回类型:
ComponentType<P>明确表示返回的组件只需要用户传入P类型的props,InjectedProps由connect负责注入,无需手动传递 - 简化中间组件:原代码中的类组件
Decorator可以简化为函数组件,既减少冗余代码,也降低了Flow的类型推导难度 - 明确mapStateToProps类型:给mapStateToProps添加返回类型标注,让Flow清晰知晓注入的props结构,避免模糊推导导致的错误
支持defaultProps的扩展场景
如果你的DecoratedComponent包含defaultProps,Flow的ComponentType会自动处理defaultProps填充后的props类型,我们只需要保持泛型P为组件的原始props(不含defaultProps的可选部分)即可:
// 示例组件,带有defaultProps const MyComponent = ({ xs, name }: { xs: string[], name?: string }) => ( <div>{name}: {xs.join(',')}</div> ); MyComponent.defaultProps = { name: 'Default Name', }; // 使用HOC时,Flow会自动推导P为{ name?: string } const InjectedComponent = injector(MyComponent); // 调用时可以不传name,因为defaultProps会自动填充 <InjectedComponent />;
原代码报错的根本原因
原代码中$Diff<ElementConfig<Com>, InjectedProps>试图从组件的实际接收props中减去注入props,但ElementConfig<Com>已经包含了defaultProps的填充逻辑,且泛型Props与Com的关联不明确,导致Flow无法确认$Diff后的类型是否合法。通过明确泛型的输入输出关系,我们彻底避免了这种模糊的类型推导问题。
内容的提问来源于stack exchange,提问作者azangru
相关产品推荐
相关产品推荐

