rxjs - Varför härleder TypeScript inte typer för vissa pipade funktioner?
Uppdatering 20 feb 2018: publicerade detta som ett problem på GitHub.
Uppdatering 28 feb: stängde det ärendet till förmån för ett nytt.
I följande kodavsnitt, om du tittar på de två sista raderna, visar TypeScript ett fel på den första och härleder korrekt typer på den andra, även om skillnaden bara är ordningen i vilken funktionerna kopplas ihop.
const pipe = <A, B, C>(
x: A,
a: (x: A) => B,
b: (x: B) => C,
) => b(a(x));
// This just calls the function passed as argument.
const call = <A, B>(f: (x: A) => B) => (x: A) => f(x)
const a = pipe(1, x => x + 1, call(x => x + 1));
const b = pipe(1, call(x => x + 1), x => x + 1);
Jag använder TypeScript 2.7.1 i strikt läge (inklusive strictFunctionTypes), men det verkar som att det strikta läget inte spelar någon roll här. Här är detta kodexempel på TypeScript playground.
Det är ett problem som jag ofta stöter på när jag arbetar med RxJS, eftersom det i RxJS finns en liknande pipe-metod och jag skickar pilfunktioner till den när jag använder skapande operatorer (som obs => merge(obs, otherObs)). Vanligtvis är det lätt att komma runt detta problem genom att specificera argumenttypen, men jag skulle vilja förstå logiken bakom detta. Varför kan TypeScript härleda typen i det ena fallet men inte i det andra?
Svar #1
Detta problem är fortfarande olöst, men för tillfället ville jag posta en lösning som jag har kommit på eftersom jag har funnit den mycket användbar i min erfarenhet.
Skapa en hjälpfunktion som denna:
export const call = <A, B>(f: (x: A) => B) => f;
(samma funktion som i frågan, en identitetsfunktion som tar en unenkel funktion som argument), och sedan, när du stöter på ett problem med en pilfunktion i din pipe, försök att omsluta den med denna hjälpfunktion. Motintuitivt kan TS inte hantera detta:
const a = pipe(1, x => x + 1, call(x => x + 1));
men det kan hantera detta:
const c = pipe(1, call(x => x + 1), call(x => x + 1));
(ingen aning varför). Senare när problemet är löst (gå vidare och rösta upp det: https://github.com/Microsoft/TypeScript/issues/22081), kommer du enkelt att kunna hitta alla referenser till call och ta bort dem.
