如何为TypeScript函数添加类型约束,确保两属性键类型一致
解决TypeScript中assign函数的类型兼容限制问题
你需要让assign函数仅允许属性值可相互赋值的键组合,核心是要在泛型中关联两个键对应的属性类型,之前的写法因为没有正确绑定泛型参数的关系,所以无法生效。
正确的实现方案
通过将两个键名K1、K2作为独立的泛型参数,结合条件类型筛选出符合赋值兼容要求的K2,就能实现类型约束:
function assign<T1, K1 extends keyof T1, T2, K2 extends keyof T2>( o1: T1, k1: K1, o2: T2, k2: K2 extends unknown ? (T2[K2] extends T1[K1] ? K2 : never) : never ) { // 这里的类型断言是安全的,因为参数层面已经做了类型兼容检查 o1[k1] = o2[k2] as T1[K1]; }
验证效果
用你给出的示例测试:
let a = { foo: 'hello', version: 10 }; let b = { bar: 'bye' }; assign(a, 'foo', b, 'bar'); // 正常通过,两者均为string类型 assign(a, 'version', b, 'bar'); // 触发类型错误,number与string类型不兼容
原理说明
- 将
K1和K2设为泛型参数,TypeScript可以精准追踪它们对应的属性类型T1[K1]和T2[K2] - 利用条件类型
T2[K2] extends T1[K1] ? K2 : never,只允许o2[k2]的类型可以赋值给o1[k1]的键名作为k2的有效值 - 函数内部的
as T1[K1]断言是因为TypeScript的类型推导在某些场景下无法自动识别兼容性,但参数层面已经做了严格检查,所以不会有类型安全问题
另一种简洁写法
你也可以通过映射类型先筛选出T2中符合条件的键,再提取这些键的联合类型作为k2的类型,效果一致:
function assign<T1, T2, K1 extends keyof T1>( o1: T1, k1: K1, o2: T2, k2: { [K in keyof T2]: T2[K] extends T1[K1] ? K : never }[keyof T2] ) { o1[k1] = o2[k2] as T1[K1]; }
内容的提问来源于stack exchange,提问作者John T.
相关产品推荐
相关产品推荐

