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

TypeScript泛型React表单Reducer:如何让Value匹配对应属性类型?

让ActionChangeInput的value类型与name对应属性类型匹配的TypeScript实现

我要实现一个通用的React表单Reducer,需要让ActionChangeInput类型中的value属性类型和泛型T里name指定的属性类型严格一致。举个例子:

type RandomObject = { test1: number, test2: string, test3: string[] }

// 原写法(无法实现预期绑定)
type ActionChangeInput<T> = {
  name: keyof T
  value: typeof T["name"] // 实际为T[keyof T],即所有属性类型的联合
}

我想要的效果是:当name为"test1"时,value必须是number类型;当name为"test2"时,value必须是string类型,以此类推。比如:

const a: ActionChangeInput<RandomObject> = {
  name: "test1",
  value: 12931 // 期望此处类型被限制为number
}

解决方案

通过映射类型转联合类型的方式,可实现name与value的类型绑定:

type RandomObject = { test1: number, test2: string, test3: string[] }

type ActionChangeInput<T> = {
  [K in keyof T]: {
    name: K
    value: T[K]
  }
}[keyof T]

原理说明

  1. 利用映射类型[K in keyof T],为T的每个键K生成对应子类型:{name: K, value: T[K]},该子类型中name是具体键名,value是对应属性的精确类型。
  2. 通过[keyof T]提取映射类型的所有值类型,组成联合类型。此时ActionChangeInput<RandomObject>等价于:
    { name: "test1", value: number } | { name: "test2", value: string } | { name: "test3", value: string[] }
    
  3. 创建对象时,TypeScript会根据name的具体值自动窄化value的类型范围,实现严格的类型匹配。

验证示例

// 合法:name为test1,value是number类型
const valid1: ActionChangeInput<RandomObject> = {
  name: "test1",
  value: 12931
}

// 合法:name为test3,value是string数组
const valid2: ActionChangeInput<RandomObject> = {
  name: "test3",
  value: ["a", "b"]
}

// 不合法:test2对应的value应为string,传number会触发类型错误
const invalid: ActionChangeInput<RandomObject> = {
  name: "test2",
  value: 123 // TypeScript报错:类型number不能赋值给类型string
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:50:26