如何用TypeScript类型检查多个Partial对象是否构成完整Interface
TypeScript 多对象合并后验证目标接口属性的实现
实现思路
- 先实现双对象合并类型:处理两个对象的属性覆盖逻辑,后传入的对象会覆盖先传入对象的同名属性。
- 再实现元组递归合并类型:遍历所有传入的参数对象,递归合并成一个最终的对象类型。
- 最后实现验证逻辑:检查合并后的最终类型是否包含目标接口的所有属性,仅允许符合条件的参数列表通过类型检查。
完整代码示例
interface Box { height: number; width: number; length: number; weight: number; } // 合并两个对象,后面对象覆盖前面对象的同名属性 type Merge<O1, O2> = Omit<O1, keyof O2> & O2; // 递归合并元组中的所有对象,得到最终合并类型 type MergeTuple<T extends any[]> = T extends [infer First, ...infer Rest] ? Merge<First, MergeTuple<Rest>> : {}; // 验证参数列表合并后是否满足目标接口,返回合法元组或触发类型错误 type Check<T extends any[], I> = MergeTuple<T> extends I ? T : never; function createBox<T extends any[]>(...args: Check<T, Box>): Box { return Object.assign({}, ...args); } // 测试用例 // ❌ 错误:缺少weight属性,TypeScript会提示类型不匹配 createBox({ height: 11, width: 15 }, { length: 24 }); // ✅ 正确:width被后续参数覆盖,合并后包含Box的所有属性 createBox({ height: 11, width: 15 }, { length: 24, width: 3, weight: 5 });
代码细节解释
Merge类型
使用Omit<O1, keyof O2>移除第一个对象中与第二个对象重复的属性,再通过交叉类型& O2合并第二个对象的属性,确保后传入的对象属性能覆盖前面的。MergeTuple类型
借助递归条件类型遍历参数元组的每一个元素,依次调用Merge完成全量合并。如果元组为空,则返回空对象{}作为初始值。Check类型
检查合并后的类型MergeTuple<T>是否是目标接口I的子类型(即包含I的所有必填属性)。如果满足条件,返回原参数元组T;否则返回never,触发TypeScript的类型错误提示。createBox函数
接收任意数量的对象参数,通过Check类型做前置验证,最终用Object.assign合并所有参数并返回符合Box接口的对象。
内容的提问来源于stack exchange,提问作者Nico Richter
相关产品推荐
相关产品推荐

