Type Parameters
- FN extends (...args: any) => any
- R extends any = ReturnType<FN>
- ARGS extends any[] = Parameters<FN>
Parameters
- fn: FN
Optional
thisArg: ThisParameterType<FN>
a series of single argument partial functions that does not evaluate until all parameters have been provided
curry a function
fn
, with optionalthisArg
option for binding as thethis
-object.what is currying? it allows a multi-parameter function to be transformed into a higher order function that always takes one argument, and spits out another function which also take only one argument, and so on... until all parameters have been filled, upon which the final function finally evaluates into the return value (type parameter R in this case).
note that this function relies on
fn.length
property to identify the number of required arguments taken byfn
. this means that default valued arguments (such asc
infn: (a: number, b: number, c = 5) => number
), or rest/spread arguments (such asargs
infn: (a: number, b: number, ...args: number[]) => number
), are not considered as required, and thus do not increment the count offn.length
.currying is usually poorly implemented through the use of closure. for instance:
this is bad because when you evaluate a curry with N-parameters, you also have to make N-calls (albeit it being tail-calls), instead of just one call, should you have had all the parameters from the beginning. not to mention that all javascript engines famously do not perform tail-call optimizations.
so here, I've implemented currying using the
bind
method, which means that once all parameters are filled, the function goes through only one call (no overheads). the same example from before would translate into the following when binding is used:do note that it is very possible for the javascript engine to internally create tail-recursion closure for every argument binding, resulting in the same unoptimized function that we discredited just a while ago. without benchmarking, I cannot say for sure which implementation is more performant.
Example