-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Allow non-generic return types to be read from single generic call signatures #54477
Allow non-generic return types to be read from single generic call signatures #54477
Conversation
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
@@ -0,0 +1,53 @@ | |||
// @strict: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test case reduced from https://github.com/Thinkmill/graphql-ts
interestingly, this one also depends on a quite recent change from #53246
declare function fn2<T>(): (cb: () => any) => (a: T) => void; | ||
const res2 = fn2()(() => res2); | ||
|
||
declare function fn3<T>(): <T2>(cb: (arg: T2) => any) => (a: T) => void; | ||
const res3 = fn3()(() => res3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only diff between those 2 is the T2
type parameter. The fn2
case works today but the fn3
doesn't - even though its return type doesn't actually depend on T2
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does fn3 fail? It looks like inference still fails, given that res3: (a: unknown) => void
-- but I'm not sure, and I don't see how to observe what's inferred for T2. Maybe the return type of fn3 should be (a: T) => T2
in the test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does fn3 fail?
We end up with: "'res3' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)"
It looks like inference still fails, given that res3: (a: unknown) => void
It doesn't exactly fail, it's just that there are no inference candidates here so the constraint is used and that's unknown
. This isn't meant to be used as a compelling use case for this PR, just a super minimal repro. The better motivating example is showcased in circularReferenceInReturnType2.ts
.
I don't see how to observe what's inferred for T2.
It's just unknown
. I re-checked this with console.log(typeToString(inference.typeParameter), typeToString(inference.inferredType))
before exiting getInferredType
.
Maybe the return type of fn3 should be (a: T) => T2 in the test?
That's not good here because that reintroduces the circularity because the return type starts to depend on a type parameter again.
…pes-avoid-circularity
@typescript-bot test this |
Heya @sandersn, I've started to run the diff-based user code test suite (tsserver) on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Heya @sandersn, I've started to run the perf test suite on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Heya @sandersn, I've started to run the diff-based user code test suite on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Heya @sandersn, I've started to run the diff-based top-repos suite (tsserver) on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Heya @sandersn, I've started to run the diff-based top-repos suite on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Heya @sandersn, I've started to run the parallelized Definitely Typed test suite on this PR at 3b17f59. You can monitor the build here. Update: The results are in! |
Hey @sandersn, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running There is also a playground for this build and an npm module you can use via |
declare function fn2<T>(): (cb: () => any) => (a: T) => void; | ||
const res2 = fn2()(() => res2); | ||
|
||
declare function fn3<T>(): <T2>(cb: (arg: T2) => any) => (a: T) => void; | ||
const res3 = fn3()(() => res3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does fn3 fail? It looks like inference still fails, given that res3: (a: unknown) => void
-- but I'm not sure, and I don't see how to observe what's inferred for T2. Maybe the return type of fn3 should be (a: T) => T2
in the test?
@sandersn Here are the results of running the user test suite comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Something interesting changed - please have a look. Details
|
@sandersn Here are the results of running the user test suite comparing Everything looks good! |
@sandersn Here they are:
CompilerComparison Report - main..54477
System
Hosts
Scenarios
TSServerComparison Report - main..54477
System
Hosts
Scenarios
StartupComparison Report - main..54477
System
Hosts
Scenarios
Developer Information: |
Hey @sandersn, the results of running the DT tests are ready. |
@sandersn Here are the results of running the top-repos suite comparing Everything looks good! |
1 similar comment
@sandersn Here are the results of running the top-repos suite comparing Everything looks good! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this isn't a bug fix, let's hold this till right at the beginning of 5.3 to give us plenty of time to watch for problems.
Discovered in microsoft#57117 The implementation should not `couldContainTypeVariables`--it's not intended a fast path, and should not be used in places where its unreliability can be observed. The tests stay, but with a note added that they should pass but do not.
This PR permits circular references in some return types of generic call signatures - something that is already allowed in non-generic call signatures.
If the return type doesn't depend on type variables then the same thing can be allowed for it (including cases with instantiated return types not depending on type variables).