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
Generic return type inferred only with explicitly typed (not inferred) parameter #31892
This is an example of the inferred return type being unknown
typeTestType={};interfaceITest<TProperty,TReturn>{option: TProperty;test(val: TProperty): TReturn;check(val: TReturn): void;}classClassTest<TProperty,TReturn>{constructor(_o: ITest<TProperty,TReturn>){// yay}}newClassTest({option: {},// val parameter properly infers the type of optiontest: _val=>({yo: {yo: {}},}),// Val's type is 'unknown' and not the return type of test :(check: val=>{val.yo;}});
With a tiny change to setting the inferred property to an explicit type, it works great now:
typeTestType={};interfaceITest<TProperty,TReturn>{option: TProperty;test(val: TProperty): TReturn;check(val: TReturn): void;}classClassTest<TProperty,TReturn>{constructor(_o: ITest<TProperty,TReturn>){// yay}}newClassTest({option: {},// We explicitly set the type this timetest: (_val: TestType)=>({yo: {yo: {}},}),// Val's type is magically known :)check: val=>{val.yo;}});
Expected behavior:
The TReturn should be inferred whether the TProperty is explicitly set in the parameter of the test method or not.
I would expect this because the system is able to infer TProperty just fine without me setting it in test.
Actual behavior:
TReturn is only inferred if TProperty for the parameter in the method is explicitly set even though TProperty can be inferred from the property just fine.
During inference (under its current algorithm), TypeScript has to resolve the entire shape of the object literal at once. At that point, there's a context-sensitive function for test, wherein the reasonable assumption is that the return type of test will rely on the parameter type for val (which in practice it always does). Therefore there's no inference candidate at all for TReturn (certainly check can't provide one) and the fallback zero-candidate unknown (previously {} is chosen instead).
The only algorithm that can correctly do this is unification (#30134) since there's no way to predict in advance how many passes* of inference need to be done before all types of parameters are resolved. The current algorithm is effectively limited to exactly three passes which are grouped by expression form.
Activity
RyanCavanaugh commentedon Jun 26, 2019
During inference (under its current algorithm), TypeScript has to resolve the entire shape of the object literal at once. At that point, there's a context-sensitive function for
test, wherein the reasonable assumption is that the return type oftestwill rely on the parameter type forval(which in practice it always does). Therefore there's no inference candidate at all forTReturn(certainlycheckcan't provide one) and the fallback zero-candidateunknown(previously{}is chosen instead).The only algorithm that can correctly do this is unification (#30134) since there's no way to predict in advance how many passes* of inference need to be done before all types of parameters are resolved. The current algorithm is effectively limited to exactly three passes which are grouped by expression form.
See also #30134
*mAAdhaTTah commentedon Oct 21, 2019
I believe I've got a stripped-down example of this problem (extracted from an attempt to make this work in a library):
yis inferred asunknown, which looks very similar to what OP posted about. Would like it to be inferred as the return type ofyx.