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 inference different between equivalent function expression and arrow function expression in object literal #38845
Just to add another data-point to the strangeness, if b is an arrow function or an anonymous function expression instead of a method-shorthand, it also gets the () => 42 type inferred for its argument:
While experimenting around this problem, I found out another strange behavior that I suspect to be related to this one:
exportdeclarefunctionfoo<C,A>(options: {c: C;a: (c: C)=>A;b: (b: A)=>void;}): void;// a(): no parameter -> return type can be inferredfoo({c: 42,a: ()=>{},// a: (c: number) => voidb(b){},// b: (b: void) => void});// a(): a parameter (with inferred type) -> return type cannot be inferredfoo({c: 42,a: (c)=>{},// a: (c: number) => unknownb(b){},// b: (b: unknown) => void});// a(): a parameter (with explicit type) -> return type can be inferredfoo({c: 42,a: (c:number)=>{},// a: (c: number) => voidb(b){},// b: (b: void) => void});
However, if function a() is the "last link in the chain", then everything works as expected:
exportdeclarefunctionfoo<C,A>(options: {c: C;a: (c: C)=>A;}): void;// a(): no parameter -> return type can be inferredfoo({c: 42,a: ()=>{},// a: (c: number) => void});// a(): a parameter -> return type can be inferredfoo({c: 42,a: (c)=>{},// a: (c: number) => void});
This is a design limitation. Similar to #38872. A arrow function with no parameters is not context sensitive, but a function expression with no parameters is context sensitive because of the implicit this parameter. Anything that is context sensitive is excluded from the first phase of type inference, which is the phase that determines the types we'll use for contextually typed parameters. So, in the original example, when the value for the a property is an arrow function, we succeed in making an inference for A before we assign a contextual type to the a parameter of b. But when the value is a function expression, we make no inferences and the a parameter is given type unknown.
Reacted by Farzad Senart, poppyLuo, blalablack, Erik, chunjin and Evgeniy Tsvigun
Activity
Nathan-Fenner commentedon May 29, 2020
Just to add another data-point to the strangeness, if
bis an arrow function or an anonymousfunctionexpression instead of a method-shorthand, it also gets the() => 42type inferred for its argument:so this suggests that the inference problem also has to do with how
bis defined, not justafsenart commentedon May 29, 2020
While experimenting around this problem, I found out another strange behavior that I suspect to be related to this one:
However, if function
a()is the "last link in the chain", then everything works as expected:RyanCavanaugh commentedon Jun 12, 2020
Anders Hejlsberg (@ahejlsberg) I tried to reason about the context-sensitiveness of this and failed. Can you weigh in, or is this just a bug?
ahejlsberg commentedon Jun 30, 2020
This is a design limitation. Similar to #38872. A arrow function with no parameters is not context sensitive, but a function expression with no parameters is context sensitive because of the implicit
thisparameter. Anything that is context sensitive is excluded from the first phase of type inference, which is the phase that determines the types we'll use for contextually typed parameters. So, in the original example, when the value for theaproperty is an arrow function, we succeed in making an inference forAbefore we assign a contextual type to theaparameter ofb. But when the value is a function expression, we make no inferences and theaparameter is given typeunknown.