JavaScript treats functions as first-class citizens, which means we can transform them in powerful ways. Two key techniques are currying and partial application—often confused but serving different purposes.
🧠 Currying: one argument at a time
Currying transforms a function with multiple arguments into a sequence of functions, each taking exactly one argument.
Think of it like a vending machine that only accepts one coin at a time.
// Regular function
function multiply(a, b, c) {
return a * b * c;
}
// Curried version
const curriedMultiply = (a) => (b) => (c) => a * b * c;
// Usage
const step1 = curriedMultiply(2);
const step2 = step1(3);
const result = step2(4); // 24
// Or chain them: curriedMultiply(2)(3)(4)
Auto-currying helper
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn(...args);
}
return (...nextArgs) => curried(...args, ...nextArgs);
};
}
const autoMultiply = curry(multiply);
// All these work: autoMultiply(2)(3)(4), autoMultiply(2, 3)(4), autoMultiply(2)(3, 4)
🧠 Partial application: preset some arguments
Partial application creates a new function by fixing some arguments, leaving the rest for later.
It's like having a form with some fields already filled out.
function greet(greeting, name, punctuation) {
return `${greeting} ${name}${punctuation}`;
}
// Partial application helper
function partial(fn, ...presetArgs) {
return (...remainingArgs) => fn(...presetArgs, ...remainingArgs);
}
// Create specialized functions
const sayHello = partial(greet, 'Hello');
const sayHelloJohn = partial(greet, 'Hello', 'John');
console.log(sayHello('Maria', '!')); // "Hello Maria!"
console.log(sayHelloJohn('.')); // "Hello John."
Real-world example
// API helper
function makeRequest(baseUrl, endpoint, method, data) {
return fetch(`${baseUrl}${endpoint}`, {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
}
// Partial application for common configurations
const api = partial(makeRequest, 'https://api.example.com');
const getUser = partial(api, '/users', 'GET');
const createUser = partial(api, '/users', 'POST');
// Usage
getUser({ id: 123 });
createUser({ name: 'John' });
🤔 Key differences
Aspect | Currying | Partial Application |
Arguments | One at a time | Some at once |
Style | f(a)(b)(c) | f_partial(b, c) |
Use case | Function composition | Pre-configured functions |
✅ When to use which?
Use Currying when:
- Building function pipelines
- You need maximum flexibility
- Working with functional programming patterns
Use Partial Application when:
- You have common configurations
- Reducing repetitive parameters
- Creating specialized versions of functions
📌 Wrapping up
Both techniques help create more reusable and readable code. Currying excels at building flexible function chains, while partial application shines at creating pre-configured, specialized functions.
Start with simple examples and gradually incorporate them where they make your code cleaner and more maintainable.