TypeScript中如何自动关联对象字段键名与对应值类型?
如何通过键名和对应值类型描述对象字段的关联类型?
你需要的是让filterField和valueThisField的类型强关联:选择某个键名时,值的类型必须严格匹配该键在IHuman中的定义。你原来的写法错误在于,keyof IHuman和IHuman[keyof IHuman]是两个独立的联合类型,TypeScript无法建立它们之间的对应关系,因此会允许键值类型不匹配的情况。
方案1:使用泛型约束实现类型关联
通过泛型约束键名,让值的类型自动关联到该键对应的类型:
interface IHuman { name: string, carModel: "Toyota" | "Mazda" | "Nissan", age: number } // 泛型类型:K必须是IHuman的键名,valueThisField严格对应IHuman[K]的类型 type TInnerField<K extends keyof IHuman> = { filterField: K; valueThisField: IHuman[K]; }; const human: IHuman = { name: "Josh", carModel: "Toyota", age: 25 }; // 错误示例:类型不匹配,会触发TypeScript报错 // const innerFieldError: TInnerField<"name"> = {filterField: "name", valueThisField: 15}; // 正确示例:类型完全匹配 const innerFieldSuccess: TInnerField<"name"> = {filterField: "name", valueThisField: "My new name"}; // 函数使用泛型,自动推导键名对应的类型 function changeHuman<K extends keyof IHuman>(humanInnerField: TInnerField<K>, human: IHuman): IHuman { return { ...human, [humanInnerField.filterField]: humanInnerField.valueThisField }; }
调用函数时无需手动指定泛型参数,TypeScript会自动推导:
// 自动推导K为"age",valueThisField必须是number类型 changeHuman({filterField: "age", valueThisField: 30}, human); // 错误:valueThisField类型不匹配,会报错 // changeHuman({filterField: "carModel", valueThisField: "Honda"}, human);
方案2:自动生成联合类型(无需泛型函数)
如果你希望直接得到所有键值组合的联合类型(和你手动编写的THumanName | THumanCarModel | THumanAge等价,但自动生成),可以用映射类型+联合提取:
interface IHuman { name: string, carModel: "Toyota" | "Mazda" | "Nissan", age: number } // 先为每个键生成对应的类型,再提取所有值的联合 type TInnerField = { [K in keyof IHuman]: { filterField: K; valueThisField: IHuman[K]; }; }[keyof IHuman]; const human: IHuman = { name: "Josh", carModel: "Toyota", age: 25 }; // 错误示例:类型不匹配,会触发报错 // const innerFieldError: TInnerField = {filterField: "name", valueThisField: 15}; // 正确示例:类型匹配 const innerFieldSuccess: TInnerField = {filterField: "name", valueThisField: "My new name"}; function changeHuman(humanInnerField: TInnerField, human: IHuman): IHuman { return { ...human, [humanInnerField.filterField]: humanInnerField.valueThisField }; }
这个TInnerField最终会被解析为:
{filterField: "name", valueThisField: string} | {filterField: "carModel", valueThisField: "Toyota" | "Mazda" | "Nissan"} | {filterField: "age", valueThisField: number}
完全等价于你手动编写的多个类型的联合,但当IHuman接口修改时,TInnerField会自动同步更新,无需手动维护。
为什么原始写法错误?
你的原始代码中:
type TInnerField = {filterField: keyof IHuman, valueThisField: IHuman[keyof IHuman]}
这里filterField是"name" | "carModel" | "age",valueThisField是string | "Toyota" | "Mazda" | "Nissan" | number,两者是独立的联合类型,TypeScript无法识别filterField的具体值对应的valueThisField应该是什么类型,因此会允许任何键和任何值类型的组合,这就是错误示例不会报错的原因。
内容的提问来源于stack exchange,提问作者xNevrroXx
相关产品推荐
相关产品推荐

