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.
Fto be inferred to be?Maybein the case ofmap(sqr, ma). But this obviously wouldn't work sinceMaybeitself isn't a type. What I would like is for the concrete implementation provided tomapto be preserved instead of returningFunctor.