Open wclr opened 6 years ago
We have no ability to get your MyFunctor<T>
and preserve MyFunctor
then return MyFunctor<U>
since we cannot get the signature of MyFunctor
itself, it seems to be a TS feature request.
interface Functor<T> {
map<U>(fn: (x: T) => U): Functor<U>;
}
// current
declare function map<T, U>(fn: (x: T) => U, functor: Functor<T>): Functor<U>;
// what you may want
declare function map<T, U, F extends Functor<T>>(
fn: (x: T) => U,
functor: F
): ???;
// ^^^ AFAIK, there's nothing we can put there to get what you want.
I expected something like this to work:
declare function map<T, U>(
fn: (x: T) => U
): <FI extends Functor<T>, FO extends Functor<U>>(f: FI) => FO
But it doesn't not. TS is disappointing often.
Also this issue probably relates to this: https://github.com/Microsoft/TypeScript/issues/1213
@ikatyang probably you can emulate HKT with same thing https://github.com/gcanti/fp-ts does
It seems HKT
uses the fake ID to match their interface and needs to register the ID on the map
signature, which seems hard to apply on npm-ramda
since we do the codegen, there's nowhere users can inject their signatures simply.
interface HKT<ID, T> {
__id: ID;
__value: T;
}
interface Functor<T> extends HKT<"Functor", T> {
map<U>(fn: (t: T) => U): HKT<"Functor", U>;
}
interface MyFunctor<T> extends HKT<"MyFunctor", T> {
map<U>(fn: (t: T) => U): HKT<"MyFunctor", U>;
}
declare function map<T, U>(fn: (x: T) => U, functor: MyFunctor<T>): MyFunctor<U>; // register
declare function map<T, U>(fn: (x: T) => U, functor: Functor<T>): Functor<U>;
declare function length(x: string): number;
declare const functor: Functor<string>;
declare const myFunctor: MyFunctor<string>;
map(length, functor); //=> Functor<number>
map(length, myFunctor); //=> MyFunctor<number>
Microsoft/TypeScript#1213 should be what we need here.
https://medium.com/@gcanti/higher-kinded-types-in-typescript-static-and-fantasy-land-d41c361d0dbe
which seems hard to apply on npm-ramda since we do the codegen,
Hm. I think everything with code gen should be more flexible.
result should be
MyFunctor<number>