J. Hesters
J. Hesters

Reputation: 14824

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?

Upvotes: 1

Views: 812

Answers (3)

ford04
ford04

Reputation: 74800

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.

Upvotes: 2

alex2007v
alex2007v

Reputation: 1300

You can declare an interface and then pass it instead of Function

interface ArrFunction<T> {
    (n: T): T
}

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

Upvotes: 2

Kamil Augustyniak
Kamil Augustyniak

Reputation: 429

You can create a function map with two parameters: array and function and when to want to use this function you should give an item from array to this function.

const double = (n: number) => n * 2;
const map = (arr: Array<any>, f: Function) => arr.map((item: any) => f(item));
map([1, 2, 3], double)

Upvotes: 0

Related Questions