如何在TypeScript中定义重载的柯里化函数?
在TypeScript中实现类型安全的通用柯里化函数
当然可行,但得借助TypeScript的函数重载和元组类型来实现——毕竟TS没法直接支持无限参数的柯里化类型推导,所以一般会设定一个合理的最大参数上限(比如10个)来覆盖绝大多数场景。
实现方案
通过手动定义不同参数数量的函数重载签名,让TS能准确推导柯里化后的函数类型,再配合通用的函数体逻辑来处理参数的累加与执行:
// 针对不同参数数量定义重载签名,可按需扩展到更多参数 function curry<R>(fn: () => R): () => R; function curry<A, R>(fn: (a: A) => R): (a: A) => R; function curry<A, B, R>(fn: (a: A, b: B) => R): (a: A) => (b: B) => R; function curry<A, B, C, R>(fn: (a: A, b: B, c: C) => R): (a: A) => (b: B) => (c: C) => R; function curry<A, B, C, D, R>(fn: (a: A, b: B, c: C, d: D) => R): (a: A) => (b: B) => (c: C) => (d: D) => R; function curry<A, B, C, D, E, R>(fn: (a: A, b: B, c: C, d: D, e: E) => R): (a: A) => (b: B) => (c: C) => (d: D) => (e: E) => R; // 通用柯里化逻辑实现 function curry(fn: (...args: any[]) => any, ...args: any[]): any { // 已传入参数数量达到原函数要求,直接执行 if (args.length >= fn.length) { return fn(...args); } // 未传够参数,返回新的柯里化函数继续接收参数 return (...nextArgs: any[]) => curry(fn, ...args, ...nextArgs); }
使用示例
这个通用函数完全可以替代你原来的curry2和curry3,并且TS能自动推导类型:
// 测试2参数函数 const add = (a: number, b: number) => a + b; const curriedAdd = curry(add); // TS正确推导类型:(a: number) => (b: number) => number console.log(curriedAdd(1)(2)); // 输出3 // 测试3参数函数 const multiply = (a: number, b: number, c: number) => a * b * c; const curriedMultiply = curry(multiply); // TS正确推导类型:(a: number) => (b: number) => (c: number) => number console.log(curriedMultiply(2)(3)(4)); // 输出24
扩展说明
如果需要支持更多参数的函数,只需要继续添加对应的重载签名即可。这种方案的类型安全性完全由你定义的重载数量决定,覆盖的参数数越多,适用场景越广。
内容的提问来源于stack exchange,提问作者Shnd
相关产品推荐
相关产品推荐

