Skip to content

Adding infer in a conditional type changes the resulting branch #22615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ivogabe opened this issue Mar 15, 2018 · 2 comments
Closed

Adding infer in a conditional type changes the resulting branch #22615

ivogabe opened this issue Mar 15, 2018 · 2 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@ivogabe
Copy link
Contributor

ivogabe commented Mar 15, 2018

TypeScript Version: 2.8.0-dev.20180315

Search Terms:
infer conditional generic function

Code

type Id = <T>(item: T) => T;

type X = ((t: Id) => void) extends (t: (item: any) => any) => void ? "yes" : "no";
// Resolves to "yes", as expected

type Y = ((t: Id) => void) extends (t: (item: any) => infer R) => void ? "yes" : "no";
// Resolves to "no", but "yes" is desired

The code checks whether a function that takes the identity function is assignable to a function that takes some function any => any. This is clearly assignable, and thus results in "yes". However, when replacing one any by infer R, the other branch is taken. I think that replacing any by an infer R type should never change the branch that is taken.

{
	"compilerOptions": {
		"allowJs": true,
		"target": "es6",
		"module": "commonjs",
		"outDir": "dest",
		"strictNullChecks": true,
		"jsx": "preserve",
		"strictFunctionTypes": true
	}
}

Expected behavior:
X and Y resolve to "yes"

Actual behavior:
Y resolves to "no"

Related Issues:

@RyanCavanaugh
Copy link
Member

@ahejlsberg bug indeed?

@ahejlsberg
Copy link
Member

It is effectively a design limitation. We have the concept of instantiating a generic function type in the context of a non-generic function type (a form of unification), but we currently don't do that in conditional types. Instead, function type parameters are erased to their constraints and we infer from those. In the example above, that causes us to infer {} for the infer R type parameter. Ordinarily that would be fine because anything is assignable to {}, however in this case the type parameter occurs in a contra-variant position, so the check fails following inference. This isn't specific to conditional types, a similar thing can happen during regular type inference in function calls.

The proper fix for this would be have type inference perform instantiation of a source type in the context of a target type when the source type is a generic function type.

@ahejlsberg ahejlsberg added this to the TypeScript 2.9 milestone Mar 21, 2018
@ahejlsberg ahejlsberg added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Bug A bug in TypeScript labels Mar 21, 2018
@ahejlsberg ahejlsberg removed this from the TypeScript 2.9 milestone Mar 21, 2018
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants