You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态推断返回组件的函数类型,消除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类型,同时满足所有约束:

  1. 创建运行时的过滤器-组件映射对象,让TypeScript自动推断其类型
  2. 从映射对象的key中推导filterType,避免重复定义
  3. 利用条件类型提取组件对应的DATA类型
  4. 重写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:55:18