Search code examples
typescriptcurryingmap-function

How to type a curried `map`?


I'm trying to type a curried map function in TypeScript. Here is the JavaScript equivalent:

const double = n => n * 2;
const map = f => arr => arr.map(f);
const doubleArr = map(double);

console.log(doubleArr([1, 2, 3]));
// ↳ [2, 4, 6]

Ideally, TypeScript should be able to infer, that after supplying double to map, doubleArray takes in an array of numbers and returns an array of numbers.

Here is what I tried:

const double = (n: number) => n * 2;
const map = (f: Function) => (arr: Array<any>) => arr.map(f);

But, TypeScript complains about f inside of map:

Argument of type 'Function' is not assignable to parameter of type '(value: any, index: number, array: any[]) => unknown'.
  Type 'Function' provides no match for the signature '(value: any, index: number, array: any[]): unknown'.

How would you type this function in TypeScript?


Solution

  • You can use the following declarations:

    const double = (n: number) => n * 2;
    const map = <A, R>(f: (arg: A) => R) => (arr: A[]) => arr.map(f);
    const doubleArr = map(double); // (arr: number[]) => number[]
    
    console.log(doubleArr([1, 2, 3]));
    // ↳ [2, 4, 6]
    

    Playground sample


    Explanation: A and R are generic type parameters. map(double) returns a function with signature (arr: number[]) => number[], because TS is able to infer from double typings, that A and R both can only be number here.