3

I am just about to learn some typed functional programming, so just started with an implementation of partial application - which should be type safe.

Problem: I am trying to make a function that takes a function and zero or all of its parameters as arguments.

So I started with that interface

interface Functor {
  (...args: any[]) => any
}

And came to this function:

const partial = <T extends Functor>(fx: T, ...apply: Parameters<T>): Functor =>
  (...args: any[]) => fx(...apply, ...args);

The Problem here is, that ...args: Parameter<T> instructs typescript to ask for all parameters, but I want allow zero up to all

Is there any way to do that?

philipp
  • 15,947
  • 15
  • 61
  • 106
  • Have you read this? https://github.com/microsoft/TypeScript/pull/30215 – Dai Jan 04 '21 at 06:47
  • Just as a side note, a functor is usually something different to a *function*. It's an algebraic structure (you can think of it as an interface) that possesses some methods to it. A plain JS array is a functor, for example due to its `.map()` method. – VLAZ Jan 04 '21 at 06:48
  • I wonder if `Partial>` would work... – Dai Jan 04 '21 at 06:49
  • No, it does not. Already tried. – philipp Jan 04 '21 at 06:53
  • @VLAZ would a plain JS Object be a functor as well? It is a structure with methods?? – philipp Jan 04 '21 at 06:58
  • @philipp it's essentially an interface. Or a design pattern, if you will. It's a structure that has methods and obeys some mathematical laws. In essence, it's just a container for a value and has a `.map()` method (although it can be called something else) which transforms that value the same way every time. With an array the `.map()` transforms every item, although you have other types of functors. A simple example is one that perseveres the null safety of the value. If you're familiar with `Optional` in Java, that's exactly it. – VLAZ Jan 04 '21 at 07:04
  • 1
    at any rate, I tracked down [the interface for `partial` in Lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/common/function.d.ts#L632). Perhaps it can help. – VLAZ Jan 04 '21 at 07:06
  • Just as [a useful resource](https://mostly-adequate.gitbooks.io/mostly-adequate-guide/content/ch08.html). I think this is pretty accessible online book on functional programming. – VLAZ Jan 04 '21 at 07:10
  • @VLAZ Thanks for that! I just came across this one last days and started to read it… Since then I decided to give FP an second try since I horribly failed first time - but back then there was no typescript… – philipp Jan 04 '21 at 07:24
  • You might also be interested in [fp-ts](https://gcanti.github.io/fp-ts/). I've not actually used it (yet) myself. – VLAZ Jan 04 '21 at 07:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226804/discussion-between-philipp-and-vlaz). – philipp Jan 04 '21 at 07:38
  • The `partialCall` example from the [official docs](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) might be helpful. Playground [link](https://www.typescriptlang.org/play?#code/C4TwDgpgBAggTnKBeKcIEMAmB7AdgGxCgFdcBrXbAd1wG0BdAbgChmAzUgY2AEs8ow6OL3T4AwqPwAeACpQIAD2ARcmAM6wEAGigBVeUpXrNcHQCUAfAApmUKGwBcUKwDo3QgOZqntNy5k6frr0AJTIFlBmWrZQfgAWGJjwXk4yzGEA3jFowMRwuM5+wOg8+MneemFIEWyubglY5YFuxaXlISwAvkA) – Chase Jan 04 '21 at 09:05

1 Answers1

2

You can define PartialParameters utility similar to builtin Parameters:

type PartialParameters<T> = T extends (...args: infer P) => any ? Partial<P> : never;

const partial = <T extends Functor>(fx: T, ...apply: PartialParameters<T>): Functor =>
(...args: any[]) => fx(...apply, ...args);

declare function foo(a: string, b: number): boolean;

partial(foo)

partial(foo, '1')

partial(foo, '1', 1)

Playground

Aleksey L.
  • 35,047
  • 10
  • 74
  • 84