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

为@expo/vector-icons的HOC创建关联子组件属性的Props类型

为@expo/vector-icons的HOC实现组件与图标名的类型关联

我正在为@expo/vector-icons编写一个高阶组件(HOC),需要给Props定义通用类型。这个模块里有多个图标源组件(比如MaterialCommunityIcons、MaterialIcons、FontAwesome等),它们结构一致,但每个组件的name属性是各自独有的字面量类型集合。

这个HOC需要接收两个Props:component(图标源组件)和name(图标名称)。我想要实现的是:当指定component后,name能自动推断出该组件对应的可用图标名称列表。

我尝试的代码如下:

const IconLibs = { MaterialCommunityIcons, MaterialIcons, FontAwesome };

type IconLibsNames = keyof typeof IconLibs;

type HocProps<Key extends IconLibsNames> = {
    component: typeof IconLibs[Key];
    name: React.ComponentProps<typeof IconLibs[Key]>["name"];
};

但实际效果是所有图标名称被合并成了一个大集合,不管选哪个component,name都能使用所有图标名。请问该如何正确拆分,让name和所选component对应起来?

补充:获取组件对应name的字面量类型有两种方式:
1.

type name = React.ComponentProps<typeof MaterialIcons>["name"]
type name = keyof typeof MaterialIcons.glyphMap

解决方案

问题出在当前泛型定义无法让TypeScript在传入具体组件时自动锁定对应的泛型参数,导致类型推断失效。可以通过联合类型映射的方式,为每个图标源组件生成专属的Props类型,实现component与name的精准关联:

import type { ComponentType } from 'react';
import { MaterialCommunityIcons, MaterialIcons, FontAwesome } from '@expo/vector-icons';

// 定义图标库映射
const IconLibs = { MaterialCommunityIcons, MaterialIcons, FontAwesome };

// 为每个图标组件生成对应的专属Props类型,再合并为联合类型
type IconComponentProps = {
  [K in keyof typeof IconLibs]: {
    component: typeof IconLibs[K];
    name: React.ComponentProps<typeof IconLibs[K]>['name'];
  };
}[keyof typeof IconLibs];

// HOC组件使用上述联合类型作为Props约束
const IconHOC = (props: IconComponentProps) => {
  const { component: Icon, name, ...rest } = props;
  return <Icon name={name} {...rest} />;
};

// 使用示例:指定component后,name会自动提示对应组件的图标名
const Test = () => {
  return (
    <>
      <IconHOC component={MaterialIcons} name="home" /> {/* 仅MaterialIcons的图标名会被提示 */}
      <IconHOC component={FontAwesome} name="star" /> {/* 仅FontAwesome的图标名会被提示 */}
    </>
  );
};

原理说明

  1. 通过[K in keyof typeof IconLibs]遍历所有图标源组件,为每个组件生成一组{ component: 组件类型, name: 对应图标名类型 }的专属Props
  2. 最后通过[keyof typeof IconLibs]提取所有专属类型的联合类型,TypeScript识别到具体的component时,会自动缩小联合类型范围,从而锁定对应的name类型

可选优化:基于glyphMap的类型定义

如果更倾向于用glyphMap获取图标名类型,可将Props类型修改为:

type IconComponentProps = {
  [K in keyof typeof IconLibs]: {
    component: typeof IconLibs[K];
    name: keyof typeof IconLibs[K]['glyphMap'];
  };
}[keyof typeof IconLibs];

内容的提问来源于stack exchange,提问作者Sander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:03:36