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

React表格组件TypeScript类型推断问题:无需显式标注实现格式化行推导

TypeScript类型推断问题:React表格组件中rowFormatter的自动类型推导

我在为React表格组件编写TypeScript类型时遇到了类型推断异常:传入数据后希望自动推断原始数据类型,但引入用于修改数据并返回新类型的rowFormatter函数后,若不显式标注rowFormatter的参数类型,getRow函数的参数类型会被推断为unknown。

简化后的类型定义如下:

type Props<TRow, TFormattedRow> = {
  data: TRow[]
  getRow?: (row: TFormattedRow) => void
  rowFormatter: (row: TRow) => TFormattedRow
}

function createProps<TRow, TFormattedRow>(props: Props<TRow, TFormattedRow>) {
  return props
}

正常工作的场景(显式标注rowFormatter参数类型)

当显式标注rowFormatter的参数类型时,getRow能正确推断格式化后的行类型为{ id: string, name: string, count: number }:

createProps({
  data: [
    { id: '1', name: 'Mangus Karlsson', count: 4 },
    { id: '2', name: 'Elsa Nyström', count: 6 },
    { id: '3', name: 'Bengt Blyertz', count: 8 },
  ],
  // getRow正确推断formattedRow类型为{ id: string, name: string, count: number }
  getRow: (formattedRow) => console.log(formattedRow),
  rowFormatter: (row: { id: string, name: string, count: number }) => {
    return { id: row.id, idAsNumber: parseInt(row.id) }
  },
})

类型推断异常的场景(不显式标注rowFormatter参数类型)

若不标注rowFormatter的参数类型,getRow的formattedRow参数类型会被推断为unknown:

createProps({
  data: [
    { id: '1', name: 'Mangus Karlsson', count: 4 },
    { id: '2', name: 'Elsa Nyström', count: 6 },
    { id: '3', name: 'Bengt Blyertz', count: 8 },
  ],
  // formattedRow被推断为unknown
  getRow: (formattedRow) => console.log(formattedRow),
  rowFormatter: (row) => {
    return { id: row.id, idAsNumber: parseInt(row.id) }
  },
})

问题原因

原类型定义中,TypeScript需要同时推断TRow和TFormattedRow两个泛型参数,但当rowFormatter参数未标注类型时,TypeScript无法确定row的类型,导致TRow推断失败,进而TFormattedRow被默认推断为unknown。

解决方案

调整泛型定义,让TypeScript先从data推断出原始行类型TRow,再基于rowFormatter的返回值自动推导格式化后的行类型。可以通过拆分泛型依赖关系实现:

// 提取rowFormatter的返回值类型作为格式化行类型
type FormattedRow<TRow, F extends (row: TRow) => any> = ReturnType<F>

type Props<TRow, F extends (row: TRow) => any> = {
  data: TRow[]
  getRow?: (row: FormattedRow<TRow, F>) => void
  rowFormatter: F
}

function createProps<TRow, F extends (row: TRow) => any>(props: Props<TRow, F>) {
  return props
}

测试验证

使用调整后的定义,无需显式标注rowFormatter的参数类型,getRow就能正确推断格式化后的行类型:

createProps({
  data: [
    { id: '1', name: 'Mangus Karlsson', count: 4 },
    { id: '2', name: 'Elsa Nyström', count: 6 },
    { id: '3', name: 'Bengt Blyertz', count: 8 },
  ],
  // formattedRow自动推断为{ id: string; idAsNumber: number; }
  getRow: (formattedRow) => console.log(formattedRow.idAsNumber),
  rowFormatter: (row) => {
    return { id: row.id, idAsNumber: parseInt(row.id) }
  },
})

原理说明

  • 先通过data推断出原始行类型TRow
  • 再将rowFormatter的类型约束为接收TRow参数的函数,TypeScript会自动推导其返回值类型作为FormattedRow
  • getRow的参数类型直接关联FormattedRow,从而实现自动推断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 13:57:03