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

如何在React组件中结合哈希映射派生类型使用泛型?

如何通过必填type prop自动推导React泛型组件的Props类型?

我在项目里有很多结构相似的React组件,想做个泛型组件消除冗余代码。这些组件的类型都继承自同一个基础类型,我期望通过必填的type prop,结合哈希映射来确定组件该使用的Props,但用type prop推导类型时碰到了TypeScript类型错误。

现有代码实现

首先定义形状枚举:

export enum Shape{
    SQUARE = "square",
    CIRCLE = "circle",
    RECTANGLE = "rectangle"
}

接着为各形状创建接口,并关联枚举与对应类型的映射:

export interface SquareComponent{
    side: number;
    color: string;
}

export interface CircleComponent{
    radius: number;
    color: string;
}

export interface RectangleComponent{
    length: number;
    height: number;
    color: string;
}

// 通过枚举值获取对应类型的哈希映射
export type ShapeConversion = {
    [T in Shape]: {
        [Shape.SQUARE]: SquareComponent;
        [Shape.CIRCLE]: CircleComponent;
        [Shape.RECTANGLE]: RectangleComponent;
    }[T]
}

然后定义泛型组件的Props接口:

export interface myComponentProps<T>{
    type: Shape, 
    shapeList: T[]
}

正常工作的两种写法

直接指定具体类型时,类型校验正常:

// 类型校验正常
const myComponent = ({type, shapeList}: myComponentProps<CircleComponent>) => {
   // 处理形状逻辑
}

通过映射指定具体枚举值时,类型校验也正常:

// 类型校验也正常
const myComponent2 = ({type, shapeList}: myComponentProps<ShapeConversion[Shape.CIRCLE]>) => {
    // 处理形状逻辑
 }

出错的写法

尝试通过传入的type prop推导类型时,出现TypeScript错误:Type 'any' cannot be used as an index type.

// 类型校验失败
const myComponent3 = ({type, shapeList}: myComponentProps<ShapeConversion[typeof type]>) => {
    // 处理形状逻辑
 }

解决方案:让泛型参数绑定到具体枚举值

要实现通过type prop自动推导泛型类型,需要把组件定义为泛型组件,让泛型参数绑定到type的具体枚举值上,而非直接使用typeof type(此时type是联合类型,无法直接作为索引)。

1. 调整Props接口

让泛型参数对应具体的Shape枚举值,而非直接对应组件类型:

export interface MyComponentProps<T extends Shape> {
    type: T;
    shapeList: ShapeConversion[T][];
}

2. 定义泛型组件

TypeScript会根据传入的type自动推导泛型参数T:

const MyComponent = <T extends Shape>({ type, shapeList }: MyComponentProps<T>) => {
    // 处理形状逻辑
    return <div>{/* 渲染内容 */}</div>;
};

3. 使用组件时自动推导类型

无需手动指定泛型参数,TypeScript会完全根据type的值推导shapeList的类型:

// 自动推导shapeList为CircleComponent[]
<MyComponent type={Shape.CIRCLE} shapeList={[{ radius: 10, color: "red" }]} />

// 自动推导shapeList为SquareComponent[]
<MyComponent type={Shape.SQUARE} shapeList={[{ side: 5, color: "blue" }]} />

额外优化:简化ShapeConversion类型

原来的映射写法可以简化为更直接的键值对形式,效果完全一致:

export type ShapeConversion = {
    [Shape.SQUARE]: SquareComponent;
    [Shape.CIRCLE]: CircleComponent;
    [Shape.RECTANGLE]: RectangleComponent;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:08:12