You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was surprised to discover that my program suddenly breaks (fails to compile) if I reorder the parameters:
functionf(a: A,c: C,b: B){// Body is completely identical}
Of course the arguments were swapped at the call site of f as well. The failure is due to type inference working differently.
Below is a complete example showing the issue.
leftJoin1 and leftJoin2 are identical functions, but with their parameter order swapped.
test1 and test2 call leftJoin1 and leftJoin2 respectively (with the appropriate argument ordering).
Notice that the pair of leftJoin1 + test1 functions works fine, while the pair of leftJoin2 + test2 functions is broken.
To really let this sink in: delete the functions leftJoin2 and test2. Then manually swap the parameters of leftJoin1 together with swapping the arguments to it in test1, and observe how the program will have changed from valid to broken.
// test1 + leftJoin1//// Both these functions compile great!//exportfunctionleftJoin1<s,aextendsobject>(q: Q<s>,s: (q: Q<Inner<s>>)=>MakeCols<Inner<s>,a>,pred: (p: MakeCols<s,a>)=>Col<s,boolean>): LeftCols<s,a>{q;pred;thrownewError("not implemented");}exportfunctiontest1<s>(q: Q<s>){leftJoin1(q,q=>select(q,addressTable),address=>stub(address.name)// Works fine! address: MakeCols<s, Address>);}// test2 + leftJoin2//// Swap the parameters and now there is an error!//exportfunctionleftJoin2<s,aextendsobject>(q: Q<s>,pred: (p: MakeCols<s,a>)=>Col<s,boolean>,s: (q: Q<Inner<s>>)=>MakeCols<Inner<s>,a>): LeftCols<s,a>{q;pred;thrownewError("not implemented");}exportfunctiontest2<s>(q: Q<s>){leftJoin2(q,address=>stub(address.name),// Error here! address: MakeCols<s, {}>q=>select(q,addressTable));}// --------------------------------------------------------------------exportclassQ<s>{privateconstructor(){}"Q": Q<s>;s: s;}exportinterfaceTable<a>{"Table": Table<a>a: a;}exportclassInner<s>{privateconstructor(){}"Inner": Inner<s>;s: s;}exporttypeMakeCols<s,Textendsobject>={[PinkeyofT]: Col<s,T[P]>;}exportclassCol<s,a>{privateconstructor(){}"Col": Col<s,a>;privates: s;privatea: a;}exporttypeLeftCols<S,A>={[PinkeyofA]: Col<S,A[P]|null>;}exportinterfaceAddress{readonlyname: string;readonlycity: string;}exportconstaddressTable=declareTable<Address>("address");exportfunctiondeclareTable<a>(tableName: string): Table<a>{tableName;thrownewError("not implemented");}exportfunctionselect<s,aextendsobject>(q: Q<s>,table: Table<a>): MakeCols<s,a>{q;table;thrownewError("not implemented");}exportfunctionstub<s,a>(e: Col<s,a>): Col<s,boolean>{e;thrownewError("not implemented");}
Thank you. That comment does explain it. And @ahejlsberg is right: turns out that leftJoin1 is indeed more "ergonomic", giving helpful autocomplete.
So type "inference working left-to-right for contextually typed arguments" is by design? It might be worthwhile to document this, since it is (at least for me) surprising behaviour that I haven't seen in any other language. Maybe in the Advanced Types section of the handbook?
Also might be worth going into more depth on what exactly a "Contextual Type" is.
Ideally order would not matter, but we have architectural constraints that prevent a fully-optimal solution. The TL;DR version is that we're not set up to contextually type a function, typecheck its body, undo that work, and then try again with a different contextual type (this could also potentially be very, very slow in certain edge cases)
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
TypeScript Version: 2.4.1
I have a function that has 3 parameters:
I was surprised to discover that my program suddenly breaks (fails to compile) if I reorder the parameters:
Of course the arguments were swapped at the call site of
f
as well. The failure is due to type inference working differently.Below is a complete example showing the issue.
leftJoin1
andleftJoin2
are identical functions, but with their parameter order swapped.test1
andtest2
callleftJoin1
andleftJoin2
respectively (with the appropriate argument ordering).Notice that the pair of
leftJoin1
+test1
functions works fine, while the pair ofleftJoin2
+test2
functions is broken.To really let this sink in: delete the functions
leftJoin2
andtest2
. Then manually swap the parameters ofleftJoin1
together with swapping the arguments to it intest1
, and observe how the program will have changed from valid to broken.tsconfig.json
The text was updated successfully, but these errors were encountered: