Why do type parameters disappear in TypeScript?
It looks like TypeScript is not capable of expressing a function that takes a generic function as a parameter and returns a generic function. Note that the generic type <A>
becomes {}
in the following code example using a function doubleton
:
function compose<A, B, C>(
g: (b: B) => C,
f: (a: A) => B): (a: A) => C {
return a => g(f(a));
}
function singleton<A>(a: A): A[] { return [a]; }
// declare var doubleton: (a: {}) => {}[];
var doubleton = compose(singleton, singleton);
Oh no! We've lost our type parameter A
.
var x = 1; // number
var xs = singleton(x); // number[]
var xss = doubleton(x); // {}[]
And now we have seen the effects of loss of doubleton
community. Because of this, number
he became {}
.
Is there a way to tell make compose
to keep these type parameters other than defining doubleton
like this:
function doubleton<A>(a: A) { return [[a]]; }
I know this seems trivial in this example, but I've run into more complex return type cases (like auto-curry functions) where there is no need to repeat.
source to share
The problem seems to be related to the way information like the shape of the function signatures interacts with the shared parameters. for example a simpler example (based on yours) that fails:
function mirror<A, B>(f: (a: A) => B)
: (a: A) => B {
return f;
}
function singleton<A>(a: A): A[] { return [a]; }
// (a:{})=>{}[]
var singletonMirror = mirror(singleton);
var x = 1;
var xs = singleton(x); // number[]
var xsM = singletonMirror(x); // {}[]
Will work unless you ask the type system to infer to A
and B
from f
:
function mirror<T>(f: T)
: T {
return f;
}
function singleton<A>(a: A): A[] { return [a]; }
// okay
var singletonMirror = mirror(singleton);
var x = 1;
var xs = singleton(x); // number[]
var xsM = singletonMirror(x); // number[]
I would report this as an issue: https://github.com/microsoft/typescript/issues
Further simplification of the error:
function unity<A>(f: (a: A) => A)
: (a: A) => A {
return f;
}
function mirror<T>(a: T): T { return a; }
// (a:{})=>{}, should be (a:T)=>T
var unityMirror = unity(mirror);
source to share