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

React表格组件:如何通过值自动关联selectionOptions属性类型?

React表格组件选择模式的自动类型推断实现

可以通过泛型条件类型实现基于selected值自动推断onChange参数类型的需求,无需辅助函数,仅通过类型定义约束即可。以下是具体实现:

import React from 'react';

// 根据selected类型映射对应的onChange函数类型
type ChangeHandler<T> = 
  T extends string ? (value: string | null) => void :
  T extends string[] ? (value: string[]) => void :
  () => void;

// 表格组件Props类型,泛型T捕获selected的类型
type TableProps<T = undefined> = {
  // 通用表格属性
  data: Record<string, unknown>[];
  columns: Array<{ key: string; label: string }>;
} & (T extends undefined 
  ? { selected?: never; onChange?: never } 
  : { selected: T; onChange: ChangeHandler<T> });

// 表格组件实现
const Table = <T extends string | string[] | undefined>(props: TableProps<T>) => {
  // 这里编写表格渲染逻辑,根据selected类型处理单选/多选交互
  return (
    <table>
      {/* 表头、表体渲染 */}
    </table>
  );
};

// 使用示例
// 单选模式:onChange参数自动推断为string | null
<Table
  data={[{ id: 'row-1', name: '张三' }]}
  columns={[{ key: 'id', label: 'ID' }, { key: 'name', label: '姓名' }]}
  selected="row-1"
  onChange={(value) => console.log('单选选中项:', value)}
/>

// 多选模式:onChange参数自动推断为string[]
<Table
  data={[{ id: 'row-1', name: '张三' }, { id: 'row-2', name: '李四' }]}
  columns={[{ key: 'id', label: 'ID' }, { key: 'name', label: '姓名' }]}
  selected={['row-1', 'row-2']}
  onChange={(value) => console.log('多选选中项:', value)}
/>

// 无选择模式:无需传入selected和onChange
<Table
  data={[{ id: 'row-1', name: '张三' }]}
  columns={[{ key: 'id', label: 'ID' }, { key: 'name', label: '姓名' }]}
/>

实现说明

  • 类型映射逻辑:ChangeHandler<T>通过条件类型,根据selected的类型(string/string[]/undefined)自动匹配对应的onChange参数类型,单选模式允许传入null来取消选中,多选模式始终传入数组(空数组代表无选中)。
  • Props约束:TableProps通过交叉类型区分三种模式的props结构,无选择模式下selected和onChange均不可传入,避免无效配置;有选择模式下强制关联selected和对应的onChange类型。
  • 自动推断:组件泛型T会自动捕获传入的selected类型,无需手动指定,保证props配置的简洁性。

内容的提问来源于stack exchange,提问作者Łukasz Falkowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:56:13