I am attempting to create a generic function interface for functor map, that respects the interface provided. In the code shown below, I would like the value of mb
to be of type Maybe<number>
, as opposed to the actual type Functor<number>
.
I do realize that one possible solution is to add an overload to the interface FMap
. The reason I am not happy with this solution is that I would like this code to reside in a package, allowing users to create implementations for Functor
, and have the behavior I described above when using the function map
.
interface Functor<A> {
map<B>(fn: (a: A) => B): Functor<B>;
}
interface FMap {
<A, B>(fn: (a: A) => B, Fa: Functor<A>): Functor<B>;
}
const map: FMap = (fn, Fa) => (
Fa.map(fn)
);
class Maybe<A> implements Functor<A> {
constructor(private readonly a: A) {}
map<B>(fn: (a: A) => B): Maybe<B> {
return new Maybe<B>(fn(this.a));
}
}
const sqr = (x: number) => x*x;
const ma = new Maybe(5);
const mb = map(sqr, ma);
I would like some means of expressing the following semantics:
// Theoretical Code
interface PretendFMap {
<A, B, FA extends Functor<A>>(fn: (a: A) => B, Fa: FA): FA extends (infer F)<A> ? F<B> : never;
}
This however does not function, as a generic interface, without a type parameter is not a valid TypeScript type, i.e. an interface such as Functor
requires a type parameter to be considered a type, Functor
itself is not a valid type.
If there are currently no means of expressing these semantics, any suggestions regarding a solution that requires as little code as possible on the side of the user would be greatly appreciated.
Thank you in advance for your time and consideration.