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
{{ message }}
Repository navigation
Using inferred return type of function as argument to same function breaks type inference #26228
My specific instance of this problem can be found here
Scroll to the very bottom to see a comment about it.
I couldn't figure out a minimal example but it looks like,
constresult1=foo(/*arg*/);//Inferred type is correctconstresult2=foo(result1);//Inferred type is wrong; shows `any`
However, if I explicitly declare the type of result1, it works,
constresult1 : number=foo(/*arg*/);//Explicitly declaredconstresult2=foo(result1);//Inferred type is correct
Or, if I do this very weird thing,
//Both foo1<>() and foo2<>() are the same, I just copy pasted foo<>() and renameddeclarefunctionfoo1</*Complicated Type*/>(/*Params*/) : /*Complicated Type*/;declarefunctionfoo2</*Complicated Type*/>(/*Params*/) : /*Complicated Type*/;constresult1=foo1(/*arg*/);//Inferred type is correctconstresult2=foo2(result1);//Inferred type is correct
Trying a type alias fails,
declarefunctionfoo</*Complicated Type*/>(/*Params*/) : /*Complicated Type*/;typeFooDelegate=</*Complicated Type*/>(/*Params*/)=>/*Complicated Type*/;constfoo1 : FooDelegate=foo;constfoo2 : FooDelegate=foo;constresult1=foo1(/*arg*/);//Inferred type is correctconstresult2=foo2(result1);//Inferred type is wrong; shows any
But this also works,
declarefunctionfoo</*Complicated Type*/>(/*Params*/) : /*Complicated Type*/;constfoo1 : </*Complicated Type*/>(/*Params*/)=>/*Complicated Type*/=foo;constfoo2 : </*Complicated Type*/>(/*Params*/)=>/*Complicated Type*/=foo;constresult1=foo1(/*arg*/);//Inferred type is correctconstresult2=foo2(result1);//Inferred type is correct
It seems like if I rely on return type inference, I have to copy-paste the function type, and cannot re-use a previous declaration.
So, if I wanted to nest the results 4 times, I'd need foo1, foo2, foo3, foo4
Right now, I just either declare the return-type explicitly, every time the function is used, or I don't use the function at all.
Can you boil this down to a standalone example? Just trimming down things from the linked file until there's nothing that doesn't need to be there should be enough. Thanks!
It took me forever, but I finally found a minimal example,
typeAssertDelegate<T>=(name: string,mixed: unknown)=>T;classField<NameTextendsstring,AssertTextendsAssertDelegate<any>>{constructor(readonlyname: NameT,readonlyassertDelegate : AssertT){}}typeTypeOf<FieldTextendsField<any,any>>=(ReturnType<FieldT["assertDelegate"]>);declarefunctionschema<FieldTextendsField<any,any>>(fields : FieldT) : (AssertDelegate<{[kinFieldT["name"]] : TypeOf<FieldT>}>);declareconstassertBoolean: AssertDelegate<boolean>;constobj=schema(newField("z",assertBoolean));constobjField=newField("obj",obj);//Incorrect;//AssertDelegate<{ obj: any; }>constactualTypeOfNested=schema(objField);//OK;//(name: string, mixed: unknown) => { obj: { z: boolean; }; }//Or,//AssertDelegate<{ obj: { z: boolean; }; }>typeexpectedTypeOfNested=AssertDelegate<{[kintypeofobjField["name"]] : TypeOf<typeofobjField>}>//COPY PASTE of schema<>()declarefunctionschema2<FieldTextendsField<any,any>>(fields : FieldT) : (AssertDelegate<{[kinFieldT["name"]] : TypeOf<FieldT>}>);//OK;//AssertDelegate<{ obj: { z: boolean; }; }>//WTF?constactualTypeOfNested2=schema2(objField);//I swear there is some kind of short-circuiting happening here.//Oh, you are trying to call `foo(foo(/*arg*/))`?//I'm too lazy, I'll just say the return type is `any`.//But if you copy-paste and make it,//`foo2(foo(/*arg*/))`,//TS goes, "Oh, okay, it's extra work but I'll do it properly"
I have all the checkboxes ticked in the Options tab; noImplicitAny, strictNullChecks, strictFunctionTypes, strictPropertyInitialization, noImplicitThis, noImplicitReturns
This behaviour is breaking my data validation library that has to validate the data type and value of nested objects in a multitude of ways. Right now, run-time validation works correctly but compile-time checks break because it infers any
declarefunctionschema<T>(value : T) : ({field : T});declareconstb: boolean;//OK;//Inferred { field : boolean }constobj=schema(b);//Incorrect;//Inferred { field : any }//Expected { field : { field : boolean }}constactualTypeOfNested=schema(obj);//Gives an error, as expected,//Type 'boolean' is not assignable to type 'number'constn: number=actualTypeOfNested.field.field;//OKconstb2: boolean=actualTypeOfNested.field.field;//Gives an error, as expected,//Type 'boolean' is not assignable to type 'number'constnotAssignable: {field: {field: number}}=actualTypeOfNested;//OKconstassignable: {field: {field: boolean}}=actualTypeOfNested;
So, it looks like the tooltip that gives the type inference is short-circuiting or something and just giving any. But the actual type checking still goes all the way.
In TS 3.0.1 with VS code (and on the Playground editor), all of a sudden, the tooltip that's supposed to give the inferred type is truncating text, and it looks like it also gives any with nested calls to the same function.
Is there any way I can get it to just display the full type truthfully, without it truncating, or giving up and displaying any? It's kind of a productivity killer when I have to second-guess the tools. They're telling me it's one thing but I check and it's another.
I remember, in TS 2.9, there wasn't truncation on the tooltip displaying inferred types.
I've tried to look at the source code a few times, cursory glances only, and it just goes over my head. Hopefully I can figure this all out at some point.
Activity
RyanCavanaugh commentedon Aug 8, 2018
Can you boil this down to a standalone example? Just trimming down things from the linked file until there's nothing that doesn't need to be there should be enough. Thanks!
AnyhowStep commentedon Aug 19, 2018
It took me forever, but I finally found a minimal example,
TS Playground link
I have all the checkboxes ticked in the
Optionstab;noImplicitAny, strictNullChecks, strictFunctionTypes, strictPropertyInitialization, noImplicitThis, noImplicitReturnsThis behaviour is breaking my data validation library that has to validate the data type and value of nested objects in a multitude of ways. Right now, run-time validation works correctly but compile-time checks break because it infers
anyAnyhowStep commentedon Aug 19, 2018
I just played with it a bit more.
TS Playground link
So, it looks like the tooltip that gives the type inference is short-circuiting or something and just giving
any. But the actual type checking still goes all the way.So, it seems like it's somewhat related to #26238
In TS 3.0.1 with VS code (and on the Playground editor), all of a sudden, the tooltip that's supposed to give the inferred type is truncating text, and it looks like it also gives
anywith nested calls to the same function.Is there any way I can get it to just display the full type truthfully, without it truncating, or giving up and displaying
any? It's kind of a productivity killer when I have to second-guess the tools. They're telling me it's one thing but I check and it's another.I remember, in TS 2.9, there wasn't truncation on the tooltip displaying inferred types.
RyanCavanaugh commentedon Aug 20, 2018
Fix bugs in the compiler 😉
RyanCavanaugh commentedon Aug 20, 2018
Wesley Wigham (@weswigham) type display issue
AnyhowStep commentedon Aug 20, 2018
I've tried to look at the source code a few times, cursory glances only, and it just goes over my head. Hopefully I can figure this all out at some point.