如何通过柯里化实现TS函数在不同页面按需返回计算值
柯里化实现按需计算方案
核心思路是把有依赖关系的计算逻辑拆成「基础公共计算+可选扩展计算」两层,通过柯里化工厂函数提前配置不同场景需要的计算范围,全程不需要字符串判断,同时完全保留原有计算的依赖关系,不会产生冗余计算。
具体实现
首先定义分层的返回类型,保证类型安全:
// 前3个值的基础返回类型 type BaseStatsResult = { value1: number; value2: number; value3: number; }; // 全量6个值的返回类型,继承基础类型 type FullStatsResult = BaseStatsResult & { value4: number; value5: number; value6: number; };
然后写柯里化的转换工厂函数,第一次调用接收扩展计算逻辑(可选),第二次调用接收原始数据执行计算:
const createStatsTransformer = <T extends BaseStatsResult = BaseStatsResult>( extraCalc?: (baseValues: BaseStatsResult, item: Data) => Omit<T, keyof BaseStatsResult> ) => { // 返回真正处理数据的函数 return (data: Data[]): T[] => { return data.map((item) => { if (!item.measurementSamples) return undefined as T; // 公共依赖计算逻辑只维护一份,所有场景复用 const value1 = // 原有value1计算逻辑 const value2 = // 原有value2计算逻辑,可直接引用value1 const value3 = // 原有value3计算逻辑,可直接引用value2、value1 const baseResult: BaseStatsResult = { value1, value2, value3 }; // 配置了扩展计算才会执行后续value4-value6的逻辑,否则直接返回基础结果 if (extraCalc) { const extraValues = extraCalc(baseResult, item); return { ...baseResult, ...extraValues }; } return baseResult; }).filter(Boolean) as T[]; // 过滤无measurementSamples的空项,可按业务需求调整 }; };
最后针对两个页面的需求,预先生成对应的转换函数即可,不需要在运行时做任何条件判断:
// 页面A专用:仅计算前3个值,不传扩展逻辑 export const transformPageAStats = createStatsTransformer(); // 页面B专用:计算全量6个值,传入后续计算逻辑 export const transformPageBStats = createStatsTransformer<FullStatsResult>((baseResult, item) => { // 直接复用已经算好的value1等依赖值,不需要重复计算 const value4 = // 原有value4计算逻辑,可直接引用baseResult.value1 const value5 = // 原有value5计算逻辑,可引用前面所有已算值 const value6 = // 原有value6计算逻辑,可引用前面所有已算值 return { value4, value5, value6 }; });
方案优势
- 无任何字符串比较逻辑,所有计算范围在函数初始化阶段确定,TypeScript可自动推导返回类型,提前发现类型错误
- 公共计算逻辑(value1-value3)仅维护一份,后续修改不需要同步改多份代码
- 页面A调用时完全不会执行value4-value6的计算逻辑,没有多余性能开销
- 完全保留原有计算的依赖关系,value3可以正常依赖value2、value4可以正常依赖value1,和原始逻辑的执行顺序完全一致
- 扩展性强,后续如果有其他页面需要不同范围的计算值,只需要传入对应的扩展逻辑调用工厂函数即可生成新的转换函数
使用时直接在对应页面引入预生成的函数即可:
// 页面A中使用,返回结果仅包含value1、value2、value3 const pageAStats = transformPageAStats(rawData); // 页面B中使用,返回结果包含全部6个属性 const pageBStats = transformPageBStats(rawData);
注:原代码中未处理
item.measurementSamples不存在时的返回值,会导致结果数组出现undefined,上述实现加了过滤逻辑,如果业务需要保留空项可移除.filter(Boolean)相关代码。
内容的提问来源于stack exchange,提问作者Rishab Gupta
相关产品推荐
相关产品推荐

