TypeScript函数工厂类型定义:实现参数部分预填的类型推导
实现支持任意参数数量的部分应用函数工厂类型
问题描述
需要为一个函数工厂创建类型,该工厂支持部分应用函数参数(预先传入部分参数,返回接受剩余参数的函数),但原实现使用Parameters工具类型时,要求必须传入函数的所有参数,导致类型报错:
type Fn = (...args: any[]) => any function apply<F extends Fn>(fn: F, ...aplyArgs: Parameters<F>) { return (...args: Parameters<F>) => fn(...(aplyArgs || []), ...(args || [])) } // 测试加法函数 function add(a: number, b: number) { return a + b } // 报错:Parameters期望2个参数,实际传入1个 const plus2 = apply(add, 2) plus2(2) // 同样报错
手动定义有限数量参数的方案不仅繁琐,无法支持任意长度参数,还存在参数长度不匹配的类型问题。
解决方案
利用TypeScript的元组切片和条件类型递归推导,可以实现支持任意参数数量的部分应用类型:
核心类型定义
// 提取函数的完整参数元组 type Args<F extends (...args: any[]) => any> = F extends (...args: infer A) => any ? A : never; // 计算部分应用后剩余的参数类型 type RestArgs<FullArgs extends any[], AppliedArgs extends any[]> = AppliedArgs extends [...infer A] ? FullArgs extends [...A, ...infer R] ? R : never : never; // 推导部分应用后返回的函数类型 type PartiallyApplied<F extends (...args: any[]) => any, AppliedArgs extends Args<F>> = (...args: RestArgs<Args<F>, AppliedArgs>) => ReturnType<F>;
实现apply函数
function apply<F extends (...args: any[]) => any, A extends Partial<Args<F>>>( fn: F, ...appliedArgs: A ): PartiallyApplied<F, A> { return (...restArgs: any[]) => fn(...appliedArgs, ...restArgs) as ReturnType<F>; }
测试验证
// 双参数函数测试 function add(a: number, b: number) { return a + b; } // 类型推导正确:plus2接受1个number参数,返回number const plus2 = apply(add, 2); plus2(3); // 类型合法,返回5 // 多参数函数测试 function multiply(a: number, b: number, c: number) { return a * b * c; } // 预先传入2个参数,返回接受1个参数的函数 const multiplyBy2And3 = apply(multiply, 2, 3); multiplyBy2And3(4); // 类型合法,返回24 // 预先传入0个参数,返回原函数类型 const originalMultiply = apply(multiply); originalMultiply(2, 3, 4); // 类型合法,返回24
关键说明
Args<F>:提取目标函数的完整参数元组,作为后续类型推导的基础RestArgs<FullArgs, AppliedArgs>:通过元组模式匹配,从完整参数中剔除已传入的部分,得到剩余需要的参数类型PartiallyApplied<F, A>:明确返回函数的参数和返回值类型,确保与原函数的类型契约一致- 泛型约束
A extends Partial<Args<F>>保证传入的部分参数与原函数参数类型完全匹配
内容的提问来源于stack exchange,提问作者Samuel Hulla
相关产品推荐
相关产品推荐

