HardPro challengeJavaScriptTypeScript

pipe() — Function Composition with Type Inference

TypeScriptTypesFunctionsPatterns

pipe(f, g, h)(x) applies functions left-to-right: h(g(f(x))). The TypeScript challenge is making the types flow through the chain:

const process = pipe(
  (x: string) => x.trim(),       // string → string
  (x: string) => x.split(','),   // string → string[]
  (x: string[]) => x.length,     // string[] → number
);

process('  a, b, c  '); // → 3
// TypeScript infers return type: number ✅
// TypeScript enforces each function receives the correct input type ✅

Overload signatures

Without overloads, pipe would return unknown. With overloads, TypeScript picks the right type per arity:

function pipe<A, B>(f: (a: A) => B): (a: A) => B;
function pipe<A, B, C>(f1: (a: A) => B, f2: (b: B) => C): (a: A) => C;
// ...

Implement

pipe(...fns) — returns a single function that applies fns left-to-right using Array.prototype.reduce.

Available transform functions for testing: double, addOne, negate, toString, toNumber, trim, upper, lower.

Sample tests

Test #1toString then lower (no change for digits)
Input: [10,["toString","lower"]]
Output: "10"
Test #23 → double → 6 → addOne → 7
Input: [3,["double","addOne"]]
Output: 7
Test #35 → negate → -5 → toString → "-5"
Input: [5,["negate","toString"]]
Output: "-5"
Test #4trim then uppercase
Input: [" hello ",["trim","upper"]]
Output: "HELLO"
Test #52 → 4 → 8 → 16 (3 doubles)
Input: [2,["double","double","double"]]
Output: 16