Closed
Description
Thoughts about unification
declare function compose<T, U, V>(a: (x: T) => U, b: (y: U) => V): (x: )
-
Works fine today if you pass it in non-generic functions, but not for if you pass in generic functions.
-
However, gives bad results today for a generic function.
-
Ideally, you'd like to be able to use compose on higher-order functions like the following:
declare function compose<T, U, V>(a: (x: T) => U, b: (y: U) => V): (x: T) => V; declare function arrayToList<T>(x: Array<T>): List<T>; declare function box<U>(x: U): { value: U }; compose(arrayToList, box) // <T>(x: Array<T>) => { value: List<T> }
-
Idea: you want to float out the free type variables into the result type for whatever doesn't get unified.
- @gcnew came the closest to getting something that would work appropriately for TypeScript
You want to build up the inferences:
declare function compose<A, B, C>(a: (x: A) => B, b: (y: B) => C): (x: A) => C;
declare function arrayToList<T>(x: Array<T>): List<T>;
declare function box<U>(x: U): { value: U };
compose(arrayToList, box);
// A = Array<T>
// B = List<T>
// B = U
// C = { value: U }
You iterate on A
, B
, and C
, finding new "truths" about the relationships between these type variables. For example, you can see that:
U = List<T>
and then
C = { value: List<T> }
But there are questions: how do you
Parameters type aliases
- Problem: you want to constrain this type to some function type.
- Otherwise you can get garbage.
- Thought: you kind of want something like
type Parameters<T extends (...args: (infer U)) => any> = U;
- Conclusion: we'll fix up the type an add it to the library.