**EDIT: updated the types in example to match what works perfectly in Flow type** <!-- BUGS: Please use this template. --> <!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript --> <!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md --> **TypeScript Version:** 2.2.1 / nightly (2.2.0-dev.201xxxxx) TypeScript is unable to infer types through higher-order functions. **Code** Given some imaginary class `SetOf`, which is just some set of values we want to compose operations over... We'll try the following: ```ts // This is a contrived class. We could do the same thing with Observables, etc. class SetOf<A> { _store: A[]; add(a: A) { this._store.push(a); } transform<B>(transformer: (a: SetOf<A>) => SetOf<B>): SetOf<B> { return transformer(this); } forEach(fn: (a: A, index: number) => void) { this._store.forEach((a, i) => fn(a, i)); } } function compose<A, B, C, D, E>( fnA: (a: SetOf<A>) => SetOf<B>, fnB: (b: SetOf<B>) => SetOf<C>, fnC: (c: SetOf<C>) => SetOf<D>, fnD: (c: SetOf<D>) => SetOf<E>, ):(x: SetOf<A>) => SetOf<E>; /* ... etc ... */ function compose<T>(...fns: ((x: T) => T)[]): (x: T) => T { return (x: T) => fns.reduce((prev, fn) => fn(prev), x); } function map<A, B>(fn: (a: A) => B): (s: SetOf<A>) => SetOf<B> { return (a: SetOf<A>) => { const b: SetOf<B> = new SetOf(); a.forEach(x => b.add(fn(x))); return b; } } function filter<A>(predicate: (a: A) => boolean): (s: SetOf<A>) => SetOf<A> { return (a: SetOf<A>) => { const result = new SetOf<A>(); a.forEach(x => { if (predicate(x)) result.add(x); }); return result; } } const testSet = new SetOf(); testSet.add(1); testSet.add(2); testSet.add(3); // THE PROBLEM IS HERE // all functions below are unable to infer any types. // The user will be required to annotate the types manually at each step. testSet.transform( compose( filter(x => x % 1 === 0), map(x => x + x), map(x => x + '!!!'), map(x => x.toUpperCase()) ) ) testSet.transform( compose( filter(x => x % 1 === 0), map(x => x + x), map(x => 123), // Whoops a bug map(x => x.toUpperCase()) // causes an error! ) ) ``` ## Libraries Where This Problem Will Exist ### RxJS We want to move RxJS over to using "lettable operators". That means operators that are built in a similar fashion to what you see in the example able. The current prototype augmentation is untenable for large applications, and makes tree-shaking hard if not impossible with regards to Rx. ### Ramda A widely popular functional programming library will undoubtedly have the same issues. Especially give that (I think) the `compose` function shown above exists (probably in a better form) within Ramdba. ### Redux `combineReducers` in redux is liable to have this same problem, at least when dealing with typed reducers. I don't think the reducer's types can be inferred inside of that call. However, I'm not sure it's a common use case for Redux to have inline reducers in a `combineReducers` call. ### Plain JavaScript This problem would exist for any higher-order function used in this manner within JavaScript: ```ts // given the same `compose` function from above: const result = [1, 2, 3, 4].map( compose( x => x + x, x => x + '!!!', x => parseInt(x) ) ); console.log(result); // [2, 4, 6, 8] ``` cc/ @rkirov @igorminar @david-driscoll @alexeagle