如何为处理函数式Mixin的Reducer函数添加TypeScript类型定义?
解决TypeScript函数式Mixin组合Reducer的类型定义问题
首先咱们得拆解你当前代码里的类型错误根源:
- Mixin函数的泛型约束逻辑倒置:你原本给
withFoo和withBar的泛型是<T extends FooComposable>,这要求传入的对象必须已经包含foo属性,但Mixin的核心作用是给对象添加新属性,而非要求对象预先拥有该属性。 - Reducer的泛型设计过于僵化:你定义的
FunctionalMixin<T>强制函数的输入输出为同一类型T,但组合多个Mixin时,每个Mixin的输出应该是前一个输出的扩展类型,而非固定的T,这直接导致了类型不兼容的报错。
接下来咱们一步步修正类型定义:
1. 修正函数式Mixin的类型
我们需要让Mixin函数接受任意对象,并返回该对象扩展了目标属性的类型。可以先定义一个通用的Mixin类型来规范这类函数:
// 通用Mixin类型:接受任意对象,返回该对象+指定属性的组合类型 type Mixin<T> = <U extends object>(base: U) => U & T; // 实现withFoo Mixin type FooComposable = { foo: string }; const withFoo: Mixin<FooComposable> = (base) => { base.foo = 'foo'; return base; }; // 实现withBar Mixin type BarComposable = { bar: string }; const withBar: Mixin<BarComposable> = (base) => { base.bar = 'bar'; return base; };
如果不想额外定义Mixin类型,也可以直接给每个Mixin函数写泛型:
const withFoo = <U extends object>(base: U): U & FooComposable => { base.foo = 'foo'; return base; }; const withBar = <U extends object>(base: U): U & BarComposable => { base.bar = 'bar'; return base; };
两种写法都能让Mixin正确表达“给对象添加属性”的语义。
2. 为Reducer函数添加正确的类型定义
我们需要让Reducer自动推断多个Mixin组合后的最终类型,这里用递归条件类型来串联所有Mixin的属性:
// 递归组合多个Mixin的属性类型 type CombineMixins<Mixins extends Array<Mixin<any>>> = Mixins extends [] ? {} // 无Mixin时返回空对象 : Mixins extends [Mixin<infer T>, ...infer Rest] ? Rest extends Array<Mixin<any>> ? T & CombineMixins<Rest> // 递归组合剩余Mixin的类型 : T : never; // 实现Reducer函数 const reduce = <M extends Array<Mixin<any>>>(...mixins: M): CombineMixins<M> => { // 用as断言初始值类型,TS无法自动推断空对象的最终组合类型 return mixins.reduce((acc, mixin) => mixin(acc), {} as CombineMixins<M>); };
3. 验证类型推断效果
现在调用reduce时,TS会自动推导出符合预期的组合类型:
const result1 = reduce(withFoo); // 类型推断为:{ foo: string; } const result2 = reduce(withBar); // 类型推断为:{ bar: string; } const result3 = reduce(withFoo, withBar); // 类型推断为:{ foo: string; } & { bar: string; }
所有类型错误都消失了,组合后的对象类型完全符合预期!
内容的提问来源于stack exchange,提问作者Mark Thë Brouch
相关产品推荐
相关产品推荐

