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

TypeScript实现数组对象属性联动 按type约束componentProps类型

数组项type与componentProps联动类型约束实现方案

核心是通过可辨识联合类型实现type值和对应componentProps的绑定校验,不需要额外类型工具,TS原生支持,具体实现步骤如下:

原有代码问题修正

你当前的代码存在几个会导致类型校验失效的问题:

  • ComTypes中重复定义了两次type2键,TS对象类型中重复键会被最后一次定义覆盖,同时缺失type3对应的类型映射
  • 泛型结构ItemProps<T>没有做联合收窄,直接作为数组类型使用时,TS无法根据传入的type值匹配对应的componentProps约束
  • 组件调用时传入的属性名是items,Props定义中写的是itemsArray,命名不一致会导致属性传参报错
  • 示例调用代码中componentProps后缺失冒号,属于语法错误

完整实现代码

import type { FC } from 'react'
// 替换成你项目中实际的FormProps类型导入
// import type { FormProps } from 'xxx'

// 1. 先定义各个type对应的componentProps类型(替换成你实际的类型结构即可)
type Type1Props = {
  // 例:input组件相关属性
  // placeholder?: string
  // maxLength?: number
}
type Type2Props = {
  // 例:select组件相关属性
  // options?: {label: string, value: string}[]
}
type Type3Props = {
  // 例:switch组件相关属性
  // defaultChecked?: boolean
}

// 2. 定义type到对应props的映射表,每个type必须唯一对应一个props类型
type ComTypes = {
  type1: Type1Props,
  type2: Type2Props,
  type3: Type3Props,
}

// 3. 生成所有合法的数组项联合类型,自动遍历所有type生成对应项结构
type ValidConfigItem = {
  [K in keyof ComTypes]: {
    type: K
    componentProps: ComTypes[K]
    showItem?: boolean
  }
}[keyof ComTypes]

// 4. 定义组件Props,注意属性名和调用端保持一致
interface AComponentProps extends FormProps {
  items: ValidConfigItem[]
}

const AComponent: FC<AComponentProps> = ({ items }) => {
  // 组件内部逻辑正常编写即可,遍历数组时TS会自动收窄类型
  items.forEach(item => {
    if (item.type === 'type1') {
      // 此处item.componentProps会自动推断为Type1Props,无需手动类型断言
      console.log(item.componentProps)
    }
  })

  return <div>{/* 组件渲染逻辑 */}</div>
}

export default AComponent

实现效果

  • 传入数组项时,只要写了type值,TS会自动匹配对应的componentProps类型要求,传错字段、漏传必填字段、字段类型错误都会直接抛出类型提示
  • 后续新增type类型时,只需要在ComTypes中补充对应的键和props类型即可,其他类型代码无需修改,会自动加入校验规则
  • 组件内部做类型判断时,TS会自动收窄对应项的componentProps类型,不需要手动写as Type1Props这类类型断言

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:36:09