// Repro from #15680 // This is a contrived class. We could do the same thing with Observables, etc. class SetOf { _store: A[]; add(a: A) { this._store.push(a); } transform(transformer: (a: SetOf) => SetOf): SetOf { return transformer(this); } forEach(fn: (a: A, index: number) => void) { this._store.forEach((a, i) => fn(a, i)); } } function compose( fnA: (a: SetOf) => SetOf, fnB: (b: SetOf) => SetOf, fnC: (c: SetOf) => SetOf, fnD: (c: SetOf) => SetOf, ):(x: SetOf) => SetOf; /* ... etc ... */ function compose(...fns: ((x: T) => T)[]): (x: T) => T { return (x: T) => fns.reduce((prev, fn) => fn(prev), x); } function map(fn: (a: A) => B): (s: SetOf) => SetOf { return (a: SetOf) => { const b: SetOf = new SetOf(); a.forEach(x => b.add(fn(x))); return b; } } function filter(predicate: (a: A) => boolean): (s: SetOf) => SetOf { return (a: SetOf) => { const result = new SetOf(); a.forEach(x => { if (predicate(x)) result.add(x); }); return result; } } const testSet = new SetOf(); testSet.add(1); testSet.add(2); testSet.add(3); 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! ) )