标准答案

  1. 泛型组件常用于 item 类型不固定但交互模式固定的组件,例如 Table<T>、Select<T>、List<T>。
  2. 泛型参数应尽量从 data、value、columns、renderItem 等 props 自动推导。
  3. 约束泛型时可以使用 extends,保证组件内部能访问必要字段,例如 id 或 key。
  4. forwardRef、memo 和泛型组合时容易丢失推导,需要显式声明函数签名或做类型包装。
  5. 类型设计要服务调用体验,过度复杂的条件类型会让错误信息难读。

题目解析

这道题考的是类型建模。泛型的价值是复用组件逻辑,同时保留业务数据类型。

如果每次使用组件都要手动写很长的泛型参数,通常说明 props 设计没有让 TypeScript 推导出足够信息。

复杂组件可以先保证核心 props 推导稳定,再逐步处理 ref、默认值和受控状态等边界。

代码示例

下面的列表组件通过 items 推导 T,再把 T 传给 renderItem。

TSX
type DataListProps<T extends { id: string }> = {
  items: T[]
  renderItem: (item: T) => ReactNode
}

function DataList<T extends { id: string }>({ items, renderItem }: DataListProps<T>) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{renderItem(item)}</li>
      ))}
    </ul>
  )
}

常见误区

  • 把泛型写得过宽,组件内部实际依赖 id、label 等字段却没有约束。
  • 所有 props 都用 any,表面通用但失去类型保护。
  • memo 或 forwardRef 包装后没有保留泛型签名,调用方推导变差。

作者信息