如何实现支持参数互斥(XOR)的TypeScript柯里化函数?
问题描述
我希望创建一个柯里化函数,要求仅能在外层调用或内层调用中传递一个参数(二者互斥,不可同时传递或都不传递)。请问是否可以实现?我无法理清实现思路,以下代码显然无法正常工作,因为未向内层函数传递类型信息:
const outerFunc: | ((outerVar: string) => (innerVar: never) => string) | ((outerVar: never) => (innerVar: string) => string) = (outerVar?: string) => (innerVar?: string): string => outerVar || innerVar // typescript still thinks this may be undefined // 应该通过的调用: outerFunc()('foo') outerFunc('foo')() // 应该失败的调用: outerFunc('foo')('foo') outerFunc()()
请问是否有技巧可以结合泛型、条件类型或函数重载来实现该需求?
解决方案
可以通过函数重载或泛型+条件类型实现这个需求,以下是两种可行方案:
方案一:函数重载实现
利用函数重载明确指定合法的调用签名,直接约束外层与内层参数的互斥关系:
// 定义重载签名,限定两种合法调用路径 function outerFunc(outerVar: string): () => string; function outerFunc(): (innerVar: string) => string; // 函数实现逻辑 function outerFunc(outerVar?: string) { if (outerVar !== undefined) { // 外层传参时,返回无参函数 return () => outerVar; } else { // 外层无参时,返回需要传参的函数 return (innerVar: string) => innerVar; } } // 合法调用(通过) outerFunc('foo')(); outerFunc()('bar'); // 非法调用(类型报错) outerFunc('foo')('bar'); // 内层函数不接受参数 outerFunc()(); // 内层函数必须传入string类型参数
这种方式通过重载签名直接划定了合法调用的边界,TypeScript会自动校验参数传递是否符合规则,同时实现逻辑通过分支判断确保了返回值的有效性,不会出现undefined问题。
方案二:泛型+条件类型实现
通过泛型捕获外层参数类型,结合条件类型动态推导内层函数的类型:
// 定义条件类型,根据外层参数类型决定内层函数结构 type CurriedResult<T extends string | undefined> = T extends string ? () => string : (innerVar: string) => string; function outerFunc<T extends string | undefined = undefined>( outerVar?: T ): CurriedResult<T> { return ( outerVar !== undefined ? () => outerVar : (innerVar: string) => innerVar ) as CurriedResult<T>; } // 合法调用(通过) outerFunc('foo')(); outerFunc()('bar'); // 非法调用(类型报错) outerFunc('foo')('bar'); // 内层函数无参数定义 outerFunc()(); // 缺少内层函数所需的string参数
这里泛型T用于捕获外层参数的实际类型,条件类型CurriedResult<T>根据T是否为string来动态生成对应的内层函数类型,同样能严格约束参数互斥的规则。
内容的提问来源于stack exchange,提问作者Adverbly
相关产品推荐
相关产品推荐

