如何实现支持批量字段类型替换的TypeScript工具类型ReplaceWithTypes
如何实现支持批量字段类型替换的TypeScript工具类型ReplaceWithTypes
嘿,刚好能解决你的问题!你已经有了单次替换字段类型的ReplaceWithType,要实现批量版本的ReplaceWithTypes其实不难,核心思路就是把批量替换拆解成多次的单次替换,用TypeScript的递归条件类型就能搞定~
首先先确认你现有的单次替换类型是没问题的:
type ReplaceWithType<O, Field extends keyof O, T> = Omit<O, Field> & Record<Field, T>;
这个类型通过Omit移除原字段,再用Record添加新类型的字段,完美实现单个字段的类型替换。
接下来直接上批量替换的实现:
// 批量替换字段类型的工具类型 type ReplaceWithTypes<O, Replacements extends [PropertyKey, any][]> = // 解构替换元组的第一个元素和剩余部分 Replacements extends [infer First, ...infer Rest] ? // 确保第一个元素是「字段名 + 目标类型」的结构 First extends [infer K extends keyof O, infer T] ? // 递归处理:把第一次替换后的对象作为新的原对象,继续处理剩余替换项 ReplaceWithTypes<ReplaceWithType<O, K, T>, Rest extends [PropertyKey, any][] ? Rest : []> : // 如果某组替换项格式不对,直接返回当前对象 O : // 所有替换项处理完,返回最终结果 O;
我给你拆解下这个类型的工作逻辑:
- 我们用元组解构把
Replacements拆成「第一个要处理的替换项」和「剩下的所有替换项」 - 每次只专注处理第一个替换项,调用你已有的
ReplaceWithType完成单次替换 - 把替换后的对象作为新的输入,递归调用
ReplaceWithTypes处理剩下的替换项 - 当没有替换项可处理时,就返回最终调整后的对象类型
给你举个实际使用的例子,一看就懂:
// 先定义测试用的类和原对象类型 class SomeClass {} type SomeObject = { foo: number; bar: boolean; baz: string; }; // 使用批量替换工具类型 type UpdatedObject = ReplaceWithTypes<SomeObject, [['foo', string], ['bar', typeof SomeClass]]>;
这个UpdatedObject的类型完全等价于你手动嵌套调用的结果:
// 等价于手动写嵌套调用 type ManualUpdated = ReplaceWithType<ReplaceWithType<SomeObject, 'foo', string>, 'bar', typeof SomeClass>;
最终UpdatedObject的结构是:
{ foo: string; // 替换成了string类型 bar: SomeClass; // 替换成了SomeClass类型 baz: string; // 未被替换的字段类型保持不变 }
如果还想支持给对象添加新字段(而不只是替换已有字段),只需要稍微修改下ReplaceWithType的约束:
// 支持添加新字段的单次替换类型 type ReplaceWithType<O, Field extends PropertyKey, T> = Omit<O, Field> & Record<Field, T>;
这样批量替换也能直接加新字段了:
type ObjectWithNewField = ReplaceWithTypes<SomeObject, [['qux', number]]>; // 最终类型会包含新字段 qux: number
内容来源于stack exchange
相关产品推荐
相关产品推荐

