动态推断返回组件的函数类型,消除getFilterComponent的any返回类型
消除
getFilterComponent返回类型中的any类型 我需要移除getFilterComponent函数返回类型里的any类型,现有代码如下:
import { type default as React } from "react"; type filterType = 'filterA' | 'filterC' | 'filterB' interface FilterProps<DATA extends Object> { type:filterType , data: DATA } function FilterACComponent({data: {a}}: FilterProps<{a: string}>){ return a } function FilterBComponent({data:{b}}: FilterProps<{b: string}>) { return b } const getFilterComponent =(type?: filterType): React.FC<FilterProps<any>> => { switch (type) { case 'filterA': case 'filterC': return FilterACComponent; case 'filterB': return FilterBComponent; default: return () => null; } };
我曾尝试过下面的写法,但需要硬编码所有组件对应的类型,在过滤器数量较多的实际场景里并不适用:
const getFilterComponent = <T extends filterType>( type?: T ): T extends 'filterAComponent' ? React.FC<FilterProps<{ a: string }>> : T extends 'filterBComponent' ? React.FC<FilterProps<{ b: string }>> : React.FC<FilterProps<any>>
实际场景的约束条件:
- 存在大量过滤器类型,需要动态推断返回组件的props类型
- 保留当前传递DATA的方式,让各组件文件自行维护对应的数据类型
- 尽量保留switch语句,因为存在多个过滤器类型对应同一组件的情况
getFilterComponent为运行时调用,无法通过静态方式调用
解决方案
通过运行时映射对象+TypeScript类型推断的方式,可以实现动态关联过滤器类型与组件props类型,同时满足所有约束:
- 创建运行时的过滤器-组件映射对象,让TypeScript自动推断其类型
- 从映射对象的key中推导
filterType,避免重复定义 - 利用条件类型提取组件对应的DATA类型
- 重写
getFilterComponent函数,基于映射对象的类型实现动态推断
完整代码如下:
import { type default as React } from "react"; interface FilterProps<DATA extends object> { type: string; data: DATA; } // 组件仍在各自文件维护DATA类型 function FilterACComponent({ data: { a } }: FilterProps<{ a: string }>) { return a; } function FilterBComponent({ data: { b } }: FilterProps<{ b: string }>) { return b; } // 运行时映射:关联过滤器类型与对应组件 const filterComponentMap = { filterA: FilterACComponent, filterC: FilterACComponent, filterB: FilterBComponent } as const; // 从映射key推导filterType,无需手动枚举 type filterType = keyof typeof filterComponentMap; // 提取组件对应的DATA类型 type ExtractFilterData<C extends React.FC<FilterProps<any>>> = C extends React.FC<FilterProps<infer D>> ? D : never; // 重写getFilterComponent,实现类型动态推断 const getFilterComponent = <T extends filterType | undefined>(type?: T): T extends keyof typeof filterComponentMap ? typeof filterComponentMap[T] : React.FC<FilterProps<{}>> => { switch (type) { case 'filterA': case 'filterC': return FilterACComponent; case 'filterB': return FilterBComponent; default: return () => null; } }; // 类型推断验证 const ComponentA = getFilterComponent('filterA'); // ComponentA类型:React.FC<FilterProps<{ a: string }>> const ComponentB = getFilterComponent('filterB'); // ComponentB类型:React.FC<FilterProps<{ b: string }>> const DefaultComponent = getFilterComponent(); // DefaultComponent类型:React.FC<FilterProps<{}>>
方案优势
- 无需硬编码每个过滤器对应的props类型,TypeScript自动从组件props中提取
- 保留了switch语句,支持多过滤器类型映射到同一组件
- 运行时调用仍能获得准确的类型推断
- 各组件的DATA类型仍由自身文件维护,符合模块化需求
内容的提问来源于stack exchange,提问作者Omran
相关产品推荐
相关产品推荐

