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

TypeScript报错:类型T不存在id属性,如何解决?

React Table泛型组件中Property 'id' does not exist on type 'T'错误的原因与修复方案

错误原因

  • 当前泛型约束仅为T extends object,TypeScript无法确认所有符合该约束的T类型都包含id属性,因此访问row.original.id时会触发类型检查错误。
  • 组件的onClick回调接收string类型的price_id参数,这隐含了数据源的每一项必须包含可传递给该回调的id属性,但当前泛型定义未体现这一强制要求。

修复方案

核心思路是给泛型T添加明确的属性约束,确保所有传入的数据源类型都包含id属性,以下是两种常用实现方式:

方式一:定义基础接口约束

先声明一个包含id属性的基础接口,让泛型T继承该接口:

// 定义基础接口,强制要求包含id属性
interface HasId {
  id: string; // 可根据实际数据类型调整,比如改为number
}

export interface ITable<T extends HasId> {
  columns: any;
  data: T[];
  with_transition?: boolean;
  onClick?: (price_id: string) => void;
}

export default function Table<T extends HasId>({
  columns,
  data,
  with_transition,
  onClick
}: ITable<T>) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow
  } = useTable({
    columns,
    data
  });
  return (
    <table {...getTableProps()}>
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            {headerGroup.headers.map(column => (
              <th {...column.getHeaderProps()}>{column.render("Header")}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody className={`${with_transition && 't-body-transition'}`} {...getTableBodyProps()}>
        {rows.map((row, i) => {
          prepareRow(row);
          return (
            <tr className="transition" {...row.getRowProps()}>
              {row.cells.map(cell => {
                return <td onClick={() => onClick && cell.column.Header !== 'Button' && onClick(row.original.id)} className="transition" {...cell.getCellProps()}>{cell.render("Cell")}</td>;
              })}
            </tr>
          );
        })}
      </tbody>
    </table>
  )
}

这种方式类型检查严格,能确保所有使用该组件的数据源都符合id属性要求。

方式二:直接在泛型约束中声明属性

如果不想额外定义接口,可直接在泛型约束中指定id属性:

export interface ITable<T extends { id: string }> {
  columns: any;
  data: T[];
  with_transition?: boolean;
  onClick?: (price_id: string) => void;
}

export default function Table<T extends { id: string }>({
  columns,
  data,
  with_transition,
  onClick
}: ITable<T>) {
  // 原有逻辑保持不变即可
}

该方式更简洁,效果与方式一完全一致。

进阶优化:让onClick参数类型与id类型联动

如果需要支持不同类型的id(比如number),可以让泛型接口的onClick参数类型自动适配T的id类型:

interface HasId<TId = string> {
  id: TId;
}

export interface ITable<T extends HasId> {
  columns: any;
  data: T[];
  with_transition?: boolean;
  onClick?: (price_id: T['id']) => void;
}

export default function Table<T extends HasId>({
  columns,
  data,
  with_transition,
  onClick
}: ITable<T>) {
  // 原有逻辑保持不变即可
}

这样当数据源的id为number类型时,onClick的参数类型会自动变为number,无需手动修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 06:27:22