type λ<TA extends any[] = any[], TR = any> = (...args: TA) => TR;
meaning λ is just any function and λ<[number], string> would be the type of a function that takes a number as its only argument and returns a string. function pipe<A>(a: A): A
function pipe<A, B>(a: A, ab: (a: A) => B): B
function pipe<A, B, C>(a: A, ab: (a: A) => B, bc: (b: B) => C): C
function pipe<A, B, C, D>(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D
...
https://github.com/gcanti/fp-ts/blob/master/src/function.ts#... double(square(half(2)))
as pipe(half, square, double)(2)
For a while now I've struggled to implement the type definition for that function, so that every passed-in function can only accept the return type of the previous function as its parameter and the resulting function will take the arguments of the first function as its parameters and return the type of the last function. pipe(() => 10, n => n.toString())
would return the type () => any
but I think that's an acceptable tradeoff because when annotated pipe(() => 10, (n: number) => n.toString())
it will return the correct type () => string
Thought the implementation might be worth sharing here in case it's useful to someone else and because it's an interesting problem to solve in TypeScript's type system. partition([1,'a',2,'b',3], (el): el is string => typeof el === 'string')
will return tuples of the type ['a','b'] and [1,2,3], not just generic arrays of type string[] and number[]. const returnCache = new Map<() => any, any>()
const memoized = <T extends () => any>(f: T): ReturnType<T> => {
if (returnCache.has(f)) return returnCache.get(f)
const v = f()
returnCache.set(f, v)
return v
}
It's included in version 0.21.0