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

如何在TypeScript泛型中正确处理对象键以适配TSX组件

TSX泛型Options组件类型修正方案

问题说明

在TSX开发中编写泛型组件时遇到类型组合问题:需要实现一个Options组件,要求:

  • 接收display参数,该参数必须是泛型类型的属性名(字符串类型)
  • 泛型类型需继承{id: string},确保传入的数组项(如PETS或USERS类型)包含id属性
  • 组件遍历数组渲染option标签,显示display指定的属性值,value绑定id

原代码问题

原组件的泛型参数U未添加约束,导致display的类型无法和Y的键关联,访问val[display]时会出现类型错误,即使使用类型断言也不够严谨。

原代码:

import React from "react";

interface IOptions<T, K extends keyof T> {
  display: K;
  values: T[];
}

const Options = <Y extends {id: string}, U>({values, display}: IOptions<Y, U>) => {
  return (
    <>
      {values.map((val: Y, index: number) => (
        <option key={index} value={val.id}>{val[display]}</option>
      ))}
    </>
  );
};

export default Options;

尝试的不严谨写法:

<option key={index} value={val.id}>{val[display as keyof Y]}</option>

修正方案

给组件的泛型参数U添加extends keyof Y的约束,让display的类型明确为Y的键,TypeScript就能正确推断val[display]的类型,无需额外断言。

修正后的代码:

import React from "react";

interface IOptions<T, K extends keyof T> {
  display: K;
  values: T[];
}

// 给U添加extends keyof Y约束,确保display是Y的合法属性名
const Options = <Y extends {id: string}, U extends keyof Y>({values, display}: IOptions<Y, U>) => {
  return (
    <>
      {values.map((val, index) => (
        <option key={index} value={val.id}>
          {val[display]}
        </option>
      ))}
    </>
  );
};

export default Options;

简化写法(可选)

也可以直接在组件props中定义泛型,无需单独的IOptions接口,让代码更简洁:

import React from "react";

const Options = <Y extends {id: string}, K extends keyof Y>({
  values,
  display,
}: {
  values: Y[];
  display: K;
}) => {
  return (
    <>
      {values.map((val, index) => (
        <option key={index} value={val.id}>
          {val[display]}
        </option>
      ))}
    </>
  );
};

export default Options;

使用示例

假设定义以下类型:

type Pet = {
  id: string;
  name: string;
  breed: string;
};

type User = {
  id: string;
  username: string;
  email: string;
};

使用组件时,TypeScript会自动推断类型,且display只能传入对应类型的合法属性名:

// 渲染宠物选项,display仅支持name/breed/id
<Options values={pets} display="name" />

// 渲染用户选项,display仅支持username/email/id
<Options values={users} display="username" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:27:43