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

AspectCurryingPartial Application
ArgumentsOne at a timeSome at once
Stylef(a)(b)(c)f_partial(b, c)
Use caseFunction compositionPre-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.