Update jquery tests for TS 5.3 #66707
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Broken by improved overload inference in microsoft/TypeScript#54448
Summary
Using
PromiseLikeorJQuery.Thenable(an alias) now correctly propagates ananyfrom theonrejectedparameter to subsequent promises like so:TS 5.2 and earlier dropped inference information between overloaded signatures. JQuery relies on this in an extremely subtle way—for
thenable, inferences came from the last overload ofJQuery.PromiseBase.then, even though the correct overload is actually the 5th one. And now that all the inferences are coming through in TS 5.3, theanyin the stdlib'sPromiseLike.thenfailure continuation has come back to bite us.The
anyis built-in to the standard lib, so anybody that usesPromiseLikeorJQuery.Thenablewill lose type information in subsequent promises. In the example, theanyfromthenableoverrides type information frompromise3becauseany| T1 | T2 | ... =anyAction
Change the tests to reflect the new 5.3 behaviour. It's unfortunate for jquery, but correct.
I haven't tried selectively deleting
ThenablefromPromiseBase.thenparameters, but that might work. But it's likely to break far more code and slow down compilation as the compiler falls back to structural comparison between Thenable and PromiseLike.Edit: No, the inference is the same, and breaks some uses of
PromiseBase.then.Explanation?!
Let's see if I can explain this in more detail:
Before the linked PR, Typescript incorrectly inferred between signatures with different numbers of overloads. If you had a target signature with 3 overloads A1, B1, C1 and source signature with two overloads B2, C2 it would look for inferences between
and then it would stop. Any possible inferences to A1 would be lost. After the linked PR, the inferences look like this:
which means that any type variables that are only in A1 may not get infererences. Why does this matter to JQuery? Well, the more common case is a single-overload source signature inferring to a multiple-overload target signature. And that's what we have with
then:Here,
t1: JQuery.Thenable<J1>andp2: JQuery.Promise3<J2, J3, J4, J5, J6, J7, J8, J9, J1>.palso has typePromise3, sofailFilter, the second parameter, has perfectly matched overloads to infer between since both signatures are fromPromise3.then. However, indoneFilter, the first parameter,t1: JQuery.Thenable<J1>only has one signature.Before, the inference would look like this:
Only one round of inference. Now,
PromiseLike.then's single signature will be used as the source for all seven ofPromiseBase.then's overloads.Why is that a problem? Well, look at
failFilter. In this overload, it'snull. So no inferences will come fromPromiseLike.onrejected. That's a good thing, becauseonrejected's has parameterreason: any. Instead, TS 5.2 would only get AJD=J3. Which is the desired inference for the test code I pasted above.In TS 5.3, the compiler will run inference against the other six overloads as well. In particular, there's one where doneFilter and failFilter are both defined (the overload that actually gets chosen, in fact):
Here, the type parameter for the first parameter of
failFilterisAJD | AJF. But nowPromiseLike.onrejected'sreason: anyis available as an inference forAJF, the inferences are AJD=J3, AJF=any, which means that the second parameter of the returnedPromiseBase,AJD | AJF, gets instantiated asJ3 | any....which is justany.