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]
原理说明
- 利用映射类型
[K in keyof T],为T的每个键K生成对应子类型:{name: K, value: T[K]},该子类型中name是具体键名,value是对应属性的精确类型。 - 通过
[keyof T]提取映射类型的所有值类型,组成联合类型。此时ActionChangeInput<RandomObject>等价于:{ name: "test1", value: number } | { name: "test2", value: string } | { name: "test3", value: string[] } - 创建对象时,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
相关产品推荐
相关产品推荐

