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 implemented terribly through the use of closure. example:
((arg0) => (arg1) => (arg2) => fn(arg1, arg2, arg3))()
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.
but 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:
fn.bind(thisArg, arg0).bind(thisArg, arg1).bind(thisArg, arg2)()
when binding is usedExample