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
Recursive generics in function parameters are inferred as {}, and produce funky Intellisense #17522
Expected behavior:
The inferred type of O should be the type of the options object passed in. self should be of type O. self.data.hello should be accessible within the processSelf function.
If this is not supposed to work, I would expect O extends Options<O> to be an error.
Actual behavior:
The inferred type of O is Options<{}>. self is of type {}. self.data.hello is therefore not accessible.
Additionally, the Intellisense VSCode is providing for this seems to be wrong, or at least confusing. If this is unrelated then I'm happy to make a separate issue for that and remove it from here.
As these screenshots show, self is inferred as {} but it allows access to self.data. self.data is given type any according to the tooltip, but the error at .hello is
Property 'hello' does not exist on type '{}'.
When I explicitly specify self: {}, self.data becomes an error.
Real scenario:
In my real scenario Options has many more optional properties, and I want self to have only the properties specified, not every optional property. There are also many optional functions with the signature of processSelf(self: TSelf) and they do need to be part of the same options object.
The problem here is that in order to get the type O in your call to build, you need to get the type of processSelf. In the body of processSelf, the properties of O are requested when using self. When that happens now, TypeScript says "stop making inferences for O" because it needs a concrete type to operate on.
But since there are no completed inferences for O while checking the inside of the object, TypeScript falls back to the type parameter's constraint (which is implicitly {}).
Anders Hejlsberg (@ahejlsberg) worked on a way to prevent this when inferring the type of this in object literals, but at this point I don't know how we'd generalize to other parameters.
it is important to note that the constraint is not an inference location. all what O extends Options<O> does is checks that whatever the compiler inferred for O is assignable to Options<O>
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
Activity
DanielRosenwasser commentedon Aug 1, 2017
The problem here is that in order to get the type
Oin your call tobuild, you need to get the type ofprocessSelf. In the body ofprocessSelf, the properties ofOare requested when usingself. When that happens now, TypeScript says "stop making inferences forO" because it needs a concrete type to operate on.But since there are no completed inferences for
Owhile checking the inside of the object, TypeScript falls back to the type parameter's constraint (which is implicitly{}).Anders Hejlsberg (@ahejlsberg) worked on a way to prevent this when inferring the type of
thisin object literals, but at this point I don't know how we'd generalize to other parameters.mhegazy commentedon Nov 6, 2017
This seems to be doable with some slight changes:
mhegazy commentedon Nov 6, 2017
it is important to note that the constraint is not an inference location. all what
O extends Options<O>does is checks that whatever the compiler inferred forOis assignable toOptions<O>typescript-bot commentedon Nov 21, 2017
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.