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

如何在TypeScript中基于对象键保留类型信息并优化数据结构?

最佳TypeScript建模与React组件渲染方案

一、核心类型定义(解决TS7053类型索引错误)

首先明确各类型Item的结构,通过联合类型+映射类型构建类型安全的对象结构:

// 定义单个类型Item的复杂结构
type StrItem = {
  type: 'Str';
  value: { content: string; maxLength: number; placeholder: string };
};

type NumItem = {
  type: 'Num';
  value: { min: number; max: number; step: number; defaultValue: number };
};

// 新增类型只需扩展此联合类型
type Item = StrItem | NumItem;

// 生成类型安全的Item对象映射:键为Item的type,值为对应类型的Item
type ItemMap = {
  [K in Item['type']]: Extract<Item, { type: K }>;
};

// 定义Section和SubSection结构
type SubSection = {
  items: ItemMap;
  // 其他子章节属性(如title、id等)
};

type Section = {
  items: ItemMap;
  subSections: SubSection[];
  // 其他章节属性
};

二、React组件映射与渲染

构建组件映射表,确保每个Item类型对应唯一组件,渲染时直接通过类型键匹配:

// 各类型Item的渲染组件
const StrItemComponent = ({ item }: { item: StrItem }) => {
  return (
    <div className="str-item">
      <input 
        type="text" 
        value={item.value.content}
        maxLength={item.value.maxLength}
        placeholder={item.value.placeholder}
      />
    </div>
  );
};

const NumItemComponent = ({ item }: { item: NumItem }) => {
  return (
    <div className="num-item">
      <input 
        type="number" 
        min={item.value.min}
        max={item.value.max}
        step={item.value.step}
        defaultValue={item.value.defaultValue}
      />
    </div>
  );
};

// 组件映射表:与Item类型一一绑定
const ItemComponentMap: Record<Item['type'], React.ComponentType<{ item: Item }>> = {
  Str: StrItemComponent,
  Num: NumItemComponent,
};

// 章节渲染组件
const SectionRenderer = ({ section }: { section: Section }) => {
  return (
    <div className="section">
      {/* 渲染当前章节的Items */}
      <div className="section-items">
        {Object.entries(section.items).map(([type, item]) => {
          const Component = ItemComponentMap[type as Item['type']];
          return <Component key={type} item={item} />;
        })}
      </div>
      {/* 渲染子章节 */}
      {section.subSections.map((subSection, idx) => (
        <div key={idx} className="sub-section">
          {Object.entries(subSection.items).map(([type, item]) => {
            const Component = ItemComponentMap[type as Item['type']];
            return <Component key={type} item={item} />;
          })}
        </div>
      ))}
    </div>
  );
};

三、方案优势

  1. 类型完全安全:通过Extract工具类型和映射类型ItemMap,彻底解决TS7053索引类型错误,TypeScript能精确推断每个键对应的Item结构。
  2. 满足业务需求:对象结构确保每个类型的Item唯一,无需关心顺序,同时支持快速通过类型键访问对应数据。
  3. 高扩展性:新增Item类型时,只需三步:
    • 新增对应XXItem类型定义
    • 扩展Item联合类型
    • 新增渲染组件并更新ItemComponentMap
  4. 代码可维护性:组件与类型一一绑定,避免分散判断逻辑,后期迭代更清晰。

可选优化:支持可选Item类型

如果部分类型的Item可能不存在,可将ItemMap改为部分映射:

type ItemMap = Partial<{
  [K in Item['type']]: Extract<Item, { type: K }>;
}>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:30:10